Railsで作っているFacebookアプリをRails3.1に更新する
HerokuでFacebookアプリを運用しており、当初はRails3.0.9ベースで作り始めたが、Railsが進化するスピードが速いので常にEdgeの状況を追いかけていたいので版をあげることにした。
基本はRailsCastsで紹介されていることをベースに修正していけばよいがいくつかはまった点があるのでメモとして残しておく。
Gemfileを更新する
Gemfileで定義しているrailsの版を3.1以降を使うように修正する。
gem '~> 3.1'
そのあとbundle updateする。
あとdeprecatedになったので、development.rbの設定で
config.action_view.debug_rjs = true
を削除しておく。
Asset Pipelineを有効化する
Rails3.1より前のRailsアプリではpublic/以下に画像やスタイルシート、JavaScriptを置いておく。もちろんこのままでもRailsは以前と変わらず動作し続けるし、問題ないけど3.1にアップグレードする意味がない。3.1にアップグレードして嬉しいことは、やはりAsset Pipelineを使えることだろう。
Gemfileに次のgemを使うように定義する。Rails3.1以降でRailsアプリを作り始めたのであれば最初から定義されているものだ。
group :assets do gem 'sass-rails', "~> 3.1" gem 'coffee-rails', "~> 3.1" gem 'uglifier', "~> 3.1" end
次に、config/application.rbでassetsの設定を記述する。Rails3.1まではapplication.rbの先頭はこのような定義だった。
# config/application.rb Bundle.require(:default, Rails.env) if defined?(Bundler)
3.1からは次のように定義されるようになった。
if defined?(Bundler) Bundler.require *Rails.groups(:assets => %w(development test)) end
さらにApplicationクラスで次の設定項目を加える
config.assets.enabled = true config.assets.version = '1.0'
また、環境毎にAsset Pipelineの挙動を変更する。開発時はデバッグを有効にして圧縮しないように設定しておくと便利だと思う(3.1のデフォルト設定)。
# config/development.rb config.assets.compress = false config.assets.debug = true
もちろんリリース時には圧縮するようにして、さらにURLにfingerprintを付け加える。
# config/production.rb config.assets.compress = true config.assets.compile = false config.assets.digest = true
assetsを移動させる
asset pipelineはapp/assets以下に保存しているものを扱う。public/images、public/javascripts、public/stylesheetsを移動させる。
$ mkdir app/assets $ mv public/images app/assets $ mv public/javascripts app/assets $ mv public/stylesheets app/assets
jQueryに関連するjavascripts以下にあるファイルは移動させなくてもよい。jquery.jsやjquery.min.js、rails.jsだ。これらは、jquery-railsのgemが保持しているものをコピーしてくれるからだ。サードパーティ製のライブラリをわざわざアプリケーション側で管理することがなくなった。
また、jQuery pluginファイルはlib/assetsやvendor/assets以下に置いたほうがよい。
次に、manifestファイルの作成にとりかかる。
デフォルトでsprocketsはassets/stylesheets/application.cssとassets/javascripts/application.jsを読み込む設定だ。application.css、application.jsで
/* *= require base */
//= require jquery //= require jquery_ujs //= require_tree .
このコメントはどのassetをコンパイルすればいいのかを示すものだ。
画像のハードコーディングを修正する
運営しているFacebookアプリではいくつか画像をハードコードしている部分があった。その場合、画像へのGETが走っても"No route matches"となってしまう。
簡単な解決方法として、
<img src="/images/please_like.jpg">
を
<img src="/assets/please_like.jpg">
に修正する。
これでdevelopmentモードの場合はうまくいくが、先ほどproductionモードではassets.digestを有効化した。そのためURLが生成されず、画像にアクセスできない。
したがってimage_tag()ヘルパーメソッドを使って画像を表示しなければならない。
さらに、CSSで背景等に画像を指定していることはよくある。
.foo-link { background:url(/images/foo-link.png) no-repeat; }
この場合は、asset_path()ヘルパーを使う。スタイルファイルを*.css.erbというファイル名に変更しておくことでerbで評価してくれたあと、CSSを出力してくれる。
.foo-link { background:url(<%= asset_path('foo-link.png') no-repeat %>) }
Herokuにデプロイする前にproductionモードで確認する
では、Herokuにデプロイする前にproductionモードでrails serverを起動してテストしよう。
$ r server -e production
こうすると/assets/{image}でアクセスできなくなった。assetを事前にコンパイルしておかなければならない。もしくはconfig/applicationで事前コンパイルを無効にしておく。
config.assets.initialize_on_precompile
HerokuでFacebookアプリを運営しているので必ずこの設定が必要だ。
そして、
$ rake assets::precompile
rakeタスクを実行してassetをコンパイルする。precompileするのはデフォルトでapp/assets/css/application.css、app/assets/javascripts/application.js なので、たとえば、アプリケーション本体と管理画面等で一つのRailsアプリのなかで分割している場合は、管理ページ側ではapplication.css等を読み込まず、admin.css等を読み込むことにしているだろう。
そこでproduction.rbにprecompileするファイルを追加する必要がある。
config.assets.precompile += %w(admin.css)
これで再度rakeタスクを実行するとadmin.cssもコンパイルしてくれるようになる。ローカルでテストして問題なければHerokuにデプロイしよう。