#282 Upgrading to Rails 3.1
Rails 3.1がついにリリースされました。新機能についての優れた概要説明がRailsGuidesサイトのリリースノートにあります。また新機能のいくつかについては、Railscastsサイトとこのサイトでも紹介されています。今回のエピソードでは、Rails 3.0アプリケーションを3.1にアップグレードする方法に焦点をあて、Railscastsサイトを例として説明していきます。
サイトを準備する
サイトをRails 3.1にアップグレードする前に、いくつかの準備作業が必要です。現在のサイトがRails 3.0の最新バージョン(現時点では3.0.10)で動いていなければ、更新を行います。これには、Gemfileでバージョンを設定してbundle
を実行します。
gem "rails", "3.0.10"
次にアプリケーションのテストスイートを実行して、テストがすべて成功することと非推奨エラー(deprecation error)が出ていないことを確認します。もしエラーがある場合は、それらを修正してからこの後の作業に進みます。Railscastsのコードはテストがすべて成功したので、引き続きアップグレード作業に移ります。
アップグレード
サイトのアップグレード作業を開始する準備ができました。これを、rails31
という名前の新しいGitブランチを作成してその中で行うことにします。
$ git checkout -b rails31
Rails 3.1へのアップグレードは至ってシンプルです。ただ単にアプリケーションのGemfile
を開いて、バージョン番号を3.1の最新リリース(現時点では3.1.0
)に変更します。
gem "rails", "3.1.0"
bundle update
を実行して新バージョンをインストールします。唯一もう一ヶ所修正が必要なのが設定ファイルのdevelopment.rb
で、次の行を削除するかコメントアウトします。
# config.action_view.debug_rjs = true
テストを再度実行すると、すべて成功します。Railsサーバを正常に起動することもでき、ブラウザから参照できます。
Asset Pipelineを使用するためのアプリケーションの修正
Asset PipelineはRails 3.1の主な新機能のひとつですが、今回のアプリケーションでは画像ファイル、スタイルシート、JavaScriptファイルがまだ/public
ディレクトリの下にあるので、その機能をまだまったく活かせていません。Asset Pipelineは完全にオプションの機能であるため、有効化させない限りはその機能は現れません。そのため、それを使うのかどうかまだわからない時点であっても、Rails 3.1へのアップグレードを思いとどまる必要はありません。アップグレードがいかに簡単かということを考えたら、それを今行わない理由はありません。
もしAsset Pipelineの機能を使いたければ、有効化する必要があります。そのためには次の行をGemfile
に追加します。(これらの行は、新規にRails 3.1アプリケーションを作成したときに生成されるGemfile
に入っています。)
# Gems used only for assets and not required # in production environments by default. group :assets do gem 'sass-rails', " ~> 3.1.0" gem 'coffee-rails', " ~> 3.1.0" gem 'uglifier' end gem 'jquery-rails'
このコードがassets
グループを作成し、そこにいくつかのアセット関連のgemを入れます。また、jquery-rails
gemをインクルードしてjQueryが使えるようにします。(もしPrototypeを使いたい場合は、代わりにprototype-rails
gemを使用します。)さらに/config/application.rb
のコードの以下の部分:
# If you have a Gemfile, require the gems listed there, including any gems # you've limited to :test, :development, or :production. Bundler.require(:default, Rails.env) if defined?(Bundler)
を以下のように書き換えます。
if defined?(Bundler) # If you precompile assets before deploying to production, use this line Bundler.require *Rails.groups(:assets => %w(development test)) # If you want your assets lazily compiled in production, use this line # Bundler.require(:default, :assets, Rails.env) end
このコードは、Bundler
で要求されるグループにassets
グループを追加します。続いてAsset Pipelineを有効化するためにこのファイルのApplication
クラスの中に次のコードを追加します。
# Enable the asset pipeline config.assets.enabled = true # Version of your assets, change this if you want to expire all your assets config.assets.version = '1.0'
このコードがAsset Pipelineを有効化し、バージョン番号を設定します。アセットに有効期限を設定したい場合はこの値を変更します。
合わせてenvironmentの各設定ファイルの設定を変更します。まず最初はdevelopment.rb
です。いくつかの箇所を変更して、アセットを圧縮せず、asset debuggingを有効化するよう設定します。
# Do not compress assets config.assets.compress = false # Expands the lines which load the assets config.assets.debug = true
次にproduction.rb
を変更します。
# Compress JavaScript and CSS config.assets.compress = true # Don't fallback to assets pipeline config.assets.compile = false # Generate digests for assets URLs config.assets.digest = true
本番モード(production mode)ではアセットを圧縮したいのですが、compile
をfalse
に設定して、プリコンパイル時にはAsset Pipelineが機能しないようにします。またdigest
をtrue
に設定して、アセットのURLがfingerprintされるようにしました。もちろん、作成するアプリケーションが本番モードでどう振舞ってほしいかに合わせて、これらのオプションを違うように設定することも可能です。
最後にテスト環境を修正します。ここではオプションを追加して、静的なアセットが返されキャッシュされるようにして、かつasset debuggingを有効化します。
# Configure static asset server for tests with Cache-Control for performance config.serve_static_assets = true config.static_cache_control = "public, max-age=3600" # Allow pass debug_assets=true as a query parameter to load pages with unpackaged assets config.assets.allow_debugging = true
アプリケーションのソースコード管理にGitを使っている場合、.gitignore
ファイルも修正して、無視する項目のリストに.sass-cache
ディレクトリを追加します。これはGitではSASSのキャッシュは不要だからです。
.sass-cache/
アセットを移動する
Asset Pipelineが設定できたので、app/assets
ディレクトリを作成します。そしてimages
、javascripts
、stylesheets
の各ディレクトリを/public
から/app/assets
に移動します。
$ mkdir app/assets $ mv public/images/ app/assets/ $ mv public/javascripts/ app/assets/ $ mv public/stylesheets/ app/assets/
移動したファイルのうちのいくつか、例えばjavascripts
ディレクトリのjQuery関連のファイルはもはや必要ありません。これらはjQuery gemに含まれているので、jquery.js
、jquery.min.js
、rails.js
は削除します。ここで、エピソード279[動画を見る, 読む]で行ったのと同じように、jQueryプラグインなどのファイルを/lib/assets
か/vendor/assets
に移すかどうかを決めておくのがいいでしょう。
次にmanifestファイルを作成します。このアプリケーションにはすでにapplication.js
ファイルとapplication.css
ファイルがそれぞれ対応するディレクトリに存在するので、新たに作成する必要はありません。ではCSSファイルから始めることにします。これをmanifestファイルにするために、最初の部分にコメントを追加してSprocketsに対してどのファイルをインクルードするかを指示します。(Sprocketsの記法についてもエピソード279で紹介しました。)Sprocketsに対して、そのファイルの残りの部分と、stylesheetsディレクトリとそのサブディレクトリ以下のその他のすべてのファイルをインクルードするように指示します。
/* *= require_self *= require_tree . */ /* rest of file omitted */
application.js
ファイルについても同じように指示できますが、ここではjQueryをインクルードしたいので、少し違う方法で行います。
//= require jquery //= require jquery_ujs //= require_self //= require_tree . /* rest of file omitted */
ここでも、ファイル自体にコードが含まれるのでrequire_self
を追加し、同じディレクトリの他のファイルがインクルードされるようrequire_tree
を追加します。
またアプリケーションのレイアウトファイルを開いてstylesheetファイルとJavaScriptファイルをインクルードしている行を修正して、関連するapplicationファイルだけを参照するようにします。というのも、その他のファイルはmanifestを介してインクルードされるからです。
<%= stylesheet_link_tag "application" %> <%= javascript_include_tag "application", "http://cdn.sublimevideo.net/js/3s7oes9q.js" %>
アプリケーションが必要とするJavaScriptファイルには、Asset Pipelineを介して読み込まれない外部ファイルも含まれます。この場合もやはり上のファイルのリストに含む必要があります。
ではここでブラウザからアプリケーションを見てみて、変更点がうまく動いているか確認します。その前にbundle
を再度実行して、追加したgemをインストールします。インストールが完了したらサーバを起動します。
$ rails s
ほとんどはうまくいきますが、一部の画像、例えば画面上部のロゴが正しく表示されません。
この問題の原因は、画像のURLがレイアウトファイルに直書きされていることにあります。
<img src="/images/railscasts_logo.png" width="423" height="56" alt="RailsCasts = Ruby on Rails Screencasts"/>
アプリケーションの画像はもう/public/images
ディレクトリにはないので、これはうまくいきません。一番簡単に解決する方法は、画像のURLを/images/railscasts_logo.png
から/assets/railscasts_logo.png
に変更することのように思えますが、 開発モードではうまく行っているように見えても、本番モードでは問題が発生します。assets.digest
オプションを有効化すると、名前の後ろにハッシュ値が追加され、それによってファイルへの静的な参照は機能しなくなります。代わりに常にヘルパーメソッドを使用するようにします。これで、開発モードと本番モードの両方で画像に正しくリンクが張られます。
<%= image_tag("railscasts_logo.png", :size => "423x56", :alt => "RailsCasts - Ruby on Rails Screencasts") %>
アプリケーション全体で検索して、静的に参照されているアセットすべてについて、上の画像のようにヘルパーメソッドを使用するよう修正します。ページを再度読み込むと画像が表示されるので、Asset Pipelineが正しく機能していることがわかります。
これでアプリケーションをRails 3.1にアップグレードする作業は終わりです。他にも便利な新機能がいくつかあるので、自分のアプリケーションの役に立つかどうかを確認するためにRails 3.1に関する他のエピソードも見てみることをお勧めします。