Railsでbowerを使ってJSのライブラリを管理する

最近Perlで仕事をしていて、cpanfileが無いプロジェクトで盛大にやらかしたtohaeです、こんにちは。
Perlでやらかした経験を生かし、Railsプロジェクトで使うクライアントサイドのJSもちゃんと管理しようとbowerを使うことにしました。

bower is 何?

bowerってのはtwitterが作ったJSのパッケージマネージャです。最近紹介記事も多いので、詳しくはぐぐってください。
簡単に言うとJSをwgetする時代は終わったってことです!!!
今回はbowerの紹介ではなく、bowerをRailsで使う場合にはbower-railsを使うといいかもというお話をします。

bower-railsの下準備

まずはbowerをnpmで入れます。

$ npm install bower -g

次にGemfileにbower-railsを追加します。現時点ではバージョンを指定しないとちょっと古いバージョンが入るので注意。

gem 'bower-rails', '0.3.1'

Railsjqueryを使う場合はjquery_ujsを使うためにjquery-railsを使ってることが多いと思いますが、jqueryjquery_ujsはbowerで管理するため、Gemfileからjquery-railsを消しておきます。

bower.jsonでなくJsfile

bowerはboewr.jsonに依存関係を定義しますが、bower-railsはGemfileのようにRubyで書きたい人のために独自のDSLが用意されています。
独自DSLを使う場合は、Jsfileというファイルを作成し、以下のように記述します

assets_path "assets/javascripts"

# Puts files under ./vendor/assets/javascripts
group :vendor do
  js 'jquery', '2.0.0'
  js 'jquery-ujs' # Assummes it's latests
  js 'jquery-autopager', 'http://lagoscript.org/files/jquery/autopager/jquery.autopager-1.0.0.js'
end

Gemfileみたいで親しみやすいですね!
このように記述して以下のコマンドを実行します。

$ rake bower:dsl:install

実行するとvendor/assets/javascripts以下にbower.jsonが作成され、それをもとにbower installがされてvendor/assets/javascripts/components以下にJSが入ります。

このままではassetsで使えないので、vendor/assets/javascripts/componentsをassets pathに追加しましょう。

# config/application.rb
config.assets.paths << Rails.root.join("vendor", "assets", "javascripts", "components")

最後にJSのrequireのパスを書き換えて完了です。今回のJsfileだと下記のような感じになります。

//= require jquery
//= require jquery-ujs/src/rails.js
//= require jquery-autopager/index.js

bowerで入るディレクトリ構成上、jquery-ujsとか若干ださい感じに…。jquery-railsはいつもどおり使った方がいいかもしれません。

cap deploy!!!!

capistranoでbundle installするような感じでbower installするとしたら、こんなタスクを書けば良さそうです。

namespace :bower do
  task :install do
    run "cd #{latest_release} && bundle exec rake bower:dsl:install"
  end

  task :update do
    run "cd #{latest_release} && bundle exec rake bower:dsl:update"
  end
end
after "deploy:finalize_update", "bower:install"

ちなみにbowerはGit Read-Onlyなgit://を使うのですが、環境によってはこのプロトコルが使えないことがあってハマりました…。そういう場合にはhttpsを使うようにgitconfigを修正すればいいようです。
参考: http://stackoverflow.com/questions/4891527/git-protocol-blocked-by-company-how-can-i-get-around-that/10729634#10729634

まとめ

こんな感じでRailsのJSをbower-railsを使ってJsfileで管理するようにしてみました。
Gemfileやpackage.jsonやcpanfileとかいろいろ便利な世の中になったなーと思いつつも、いろんな言語を触るとそれぞれ少しずつ違ってイラっしてたんですが、今回紹介したJsfileはRubyでGemfileのように記述できるのでおすすめです。

2012年の振り返りと2013年の抱負

年が明けてだいぶ経ちましたが、あけましておめでとうございます。
1/5に27歳になり、本格的なアラサーになりつつありますが今年もよろしくお願いします。
ちなみに例のリストはこちらです!!! http://www.amazon.co.jp/registry/wishlist/MRQ3OS6NAULY

振り返り

去年はRailsECサイト?をやったり、ついカッとなって転職したり、転職後にPerlができるようになりつつあったらサンフランシスコでRuby書いてたりしました。
前半はあまり成長してる感が無かったのですが、転職してからはPerlやったり、成功してるサービスのPDCAの回し方を知ったり、GitHubを使った開発とか、海外での働き方とか、英語とか、いろいろ新しい体験もできてよかったかなぁと思います。
まぁ良くも悪くも海外出張が一番印象に残ってますね。
英語できないのはやっぱり辛かったです。言ってることは1割くらいしかわからないし(技術的な話題ならもう少しわかる)、言いたいことは1%も伝えられないしで無力さを痛感しました。
あとGitHubを使った開発は実に良いです。pull request使うとレビューが割りとうまく回る気がします。レビューされるのはありがたいです。前職で導入しようとちょっと動いたけどもっと真剣に動いておけばよかったとちょっと後悔するくらいです。

日本ではPerlだけど、サンフランシスコではRubyが使われてて、Rails以外で書かれたコンポーネントもあり、今まではRailsばかりやってきたので色々勉強になりました。ただ前職で約2年間、経験あるRubyistもいない状況でいろいろ模索しながらやってきたことは無駄ではなくて、他の環境でもちゃんと通用することがわかったのは良かったです。

抱負

今年はPerlを書くことになりそうな雰囲気が今のところあります。Perlは色々disりたいところが多々あり、勉強する意欲がなかなか湧いてこないのですが、チームの人達の足を引っ張らない程度にはちゃんと使えるようになりたいです。それと同時にPerlはやっぱり嫌でRubyPythonが好きという気持ちもあるので、RubyPythonの仕事を産み出せたら良いなと思っています。
あとはGitHubの使い方もだんだんわかってきたので、今年は何らかのオープンソースにpull requestを送りたいです。perlのHTTP::Sessionに投げたpull requestがマージされたので*1、この調子でがんばりたいです。英語もpull requestを送るときに不自由しない程度にはできるように勉強しようかと思います。


というわけで今年もよろしくお願いします!!!

*1:ノーテストでpull requestしたら「テスト書けや」って怒られたりしたけど…

退職しました2

入社して2年3ヶ月勤めたOKWaveを退職しました。
Q&Aサービスでいろいろやってやろうと思って入社したら、新規サービス開発をやることになってRailsをやることになり*1、Rails3へのバージョンアップや、Prototype.jsからjQueryとCoffeeScriptへの移行や、テストコードとCIの導入とか、デプロイ方法の変更とか、Gitへの移行とか、開発機をMacに移行とか、開発基盤もどきなこととか、新人教育とか、ちょっとしたマネージメントもどきとか、サービス開発だけでなく開発環境をよくするための色々を好き勝手やらせてもらってました。
小さなサービスとチームを大きくする楽しみは大きく、あっという間の2年3ヶ月でしたが、いろいろ思うところがあって転職することにしました。

辞めた理由

大きな理由としては、ユーザーやアクセス数が多く、ちゃんとマネタイズができるWebサービスを作りたくなったからです。
新規サービスを作るチームはいろんなことを一から決めれる楽しさがあるんですが、新規サービスはなかなか流行らないので色々と辛くなっていきます。
流行ってないなら問題を見つけ出して少しずつ改善して徐々に伸ばしていくか、見切りをつけて閉じるかができればよかったんですが、いろんな事情があって難しかったので転職することにしました。
あとはここ半年くらいのプロジェクトの意思決定の仕方とかスピードとかも嫌だったんですけど、まぁそのあたりはもう解消されたので良いです。

次の会社

次は渋谷で1軍定着を目指して野球をがんばります。
前までは「人の役に立つサービス」をやってることと、Perl以外の言語を使ってる会社を重要視してたんですが、ここ2年の鬱憤がたまって、多くの人に使われてちゃんとお金を稼いでるサービスを作りたくなりました。
最近はRubyばっかりだったのでRubyの会社に行きたい気持ちもありましたが、言語よりもユーザー数や金儲けの方を今回は重要視しました。あとRuby使ってるそれっぽいイケてる会社は球団を持ってないですからね!!!
まぁ球団があることを理由にするとみんなに笑われてネタのように思われるんですけど、みんな野球がおもしろいことを知らなすぎますし、球団買って何かおもしろいことをしようとしてるのはちょっと感じましたし、さらにインターネットの力で球団の暗黒時代を脱出させられたらおもしろいと思います。でもたぶん野球に関する開発はやらなさそうです…。


他にも辞めた理由とか次を決めた理由とかもうちょい色々あるんですが、うまく表現できなかったので会った時にでも聞いてください。明日の出社用の提出書類が半分以上揃えられてないけど寝ます。9時半出社を強いられてるんだ!!!

*1:結果として良かった

Redis.newする時にloggerを設定して、rails consoleに実行したredisのクエリを表示する

タイトルのまんまなんだけども、一応やり方を。

Redis.new :logger => ActiveRecord::Base.logger

これだけ。Rails.loggerじゃなくてActiveRecord::Base.loggerを使えばrails consoleにクエリとかかった時間などが表示される。便利。

Rails3.2.6に上げたらDEPRECATION_WARNINGが出たので対応した

http://weblog.rubyonrails.org/2012/6/12/ann-rails-3-2-6-has-been-released/

先日Rails3.2.6が出て、SQLインジェクションとかあるから(´∀`∩)↑age↑てくださいと言われたので、重い腰を上げてRails3.2.2から3.2.6にバージョンを上げた。
テスト流したらDEPRECATION_WARNINGがいっぱい出たのでその対応方法を一応書いとく

:confirm option is deprecated and will be removed from Rails 4.0

= link_to "hoge", hoge_path, :method => :delete, :confirm => "フォーマットするのか?"

上のようにviewでaタグとかに:confirmと書いておくと、確認用のダイアログを出してくれるRails(jquery_ujs)の便利機能がある。
削除リンクとかでよく使ってたんだけど、この書き方がRails4.0から使えなくなるらしい。

= link_to "hoge", hoge_path, :method => :delete, :data => {:confirm => "フォーマットするのか?"}

で、対処方法は:confirmではなく、:data => {:confirm => ""}を使いましょうとのこと。書く量が増えてめんどくさいです…

:disable_with option is deprecated and will be removed from Rails 4.0

= submit_tag("Submit", :disable_with => "Sending...")

上のようにViewでsubmitとかに:disable_withを書くと、フォームの二度押しを防ぐことができる便利機能がある。Rails3レシピブックにも紹介されてます。
これまた楽だからよく使ってたんだけど、Rails4.0で無くなるらしい。

= submit_tag("Submit", :data => {:disable_with => "Sending..."})
confirmの時と同じように、
dataの中に入れれば良いとのこと。これまた書く量が増えてだるい…。

他にもいろいろありそうだけど、ひとまずWARNINGが出たのはこの2つでした。
新しいバージョンが出るたびにちゃんと追って行かないとRails4系に上げるのが大変そうなので、今後はサボらずにバージョンをあげていこうと思った。

セッションの保存先にRedisを使う

Railsのデフォルトだとセッションの保存先はCookieになるけど、様々な事情からサーバ側にセッションのデータを持ちたくなることがある。
Railsはセッションの保存先をMySQLにすることもできるけど、expireがめんどくさいとか他いろいろを考えて使いたくない。
memcachedを使うのが一般的な気もするけど、memcachedをインストールするのがめんどくさかったので、今回はRedisを保存先に使うことにした。*1

redis-storeとredis-railsを使う

https://github.com/jodosha/redis-store/
https://github.com/jodosha/redis-store/tree/master/redis-rails

このgemを使うとRailsとかSinatraとかRackとかのキャッシュやセッションの保存先にRedisを使うようにすることができる。便利。Railsの場合はredis-railsを使う。

config/initializers/session.rb を編集する
Hoge::Application.config.session_store :redis_store, :servers => "redis://localhost:6379/1", :expire_in => 60 * 60 * 24 * 7 * 2 

session_storeの指定のところを:redis_storeに書き換え、:serversでRedisの接続先を指定する。
Redisはdbを複数持てるので、セッション用にdbを指定した方が良いと思う。

expire_in は2.weeks.agoのように指定したいところだけど、redis-storeの中で
expire_inで指定した値をto_iしてたので、 60 * 60 * 24 * 7 * 2 のように書いてる。

最後にrailsを再起動すればCookieの時と同じコードで動く。簡単。
ただCookieで動いてたものをRedisに切り替えると、それまでログインしてたユーザーがログアウト状態になるのでお気をつけて。

*1:RedisはResqueを使ってる関係上すでにインストールされてた

GCを止めてrspecを高速化する

https://makandracards.com/makandra/950-speed-up-rspec-by-deferring-garbage-collection

GCを止めてrspecを高速化しようという話。
やり方は簡単で上記のリンクにあるコードをspec/support以下にでもおいて、spec_helper.rbにbefore(:all)とafter(:all)を書き足せばいいだけ。
上記のコードだとデフォルトで10秒間に1回だけ行うようになってるがENVで秒数は指定できる。
文中には15%の高速化とあるけど、手元のコードもだいたいそれくらい速くなった。

ただ実際に動かすとわかるけど、メモリをめっちゃ食う。
手元の環境(iMac 21.5-inch, Mid 2011 メモリ8GB)だとrspec自体は2〜3分で、メモリは残り100MBくらいまでになる

https://github.com/diaspora/diaspora/blob/master/spec/support/deferred_garbage_collection.rb

def self.memory_threshold
  @mem = %x(free 2>/dev/null).to_s.split(" ")
  return nil if @mem.empty?
  @mem[15].to_i / (@mem[7].to_i/100)
end 

ちょっと前に話題になったdiasporaだと上のようにしてメモリ使用量を取得して、メモリが90%以上になったらGC.startしてるけど、Macだとfreeコマンドが使えないからうまくいかない。
他にもググるとexampleを実行した回数がn回になるまでGCを止めるという方法が出てくるけどどうなんだろう?
全体のテストはリモートのLinuxマシンでやらせればいいという話もあるんだけど、どうにかしてうまくできないもんかなー。