homeASCIIcasts

282: Rails 3.1へのアップグレード 

(view original Railscast)

Other translations: En Es Ru Fr

Other formats:

Written by Naomi Fujimoto

Rails 3.1がついにリリースされました。新機能についての優れた概要説明がRailsGuidesサイトのリリースノートにあります。また新機能のいくつかについては、Railscastsサイトこのサイトでも紹介されています。今回のエピソードでは、Rails 3.0アプリケーションを3.1にアップグレードする方法に焦点をあて、Railscastsサイトを例として説明していきます。

サイトを準備する

サイトをRails 3.1にアップグレードする前に、いくつかの準備作業が必要です。現在のサイトがRails 3.0の最新バージョン(現時点では3.0.10)で動いていなければ、更新を行います。これには、Gemfileでバージョンを設定してbundleを実行します。

/Gemfile

gem "rails", "3.0.10"

次にアプリケーションのテストスイートを実行して、テストがすべて成功することと非推奨エラー(deprecation error)が出ていないことを確認します。もしエラーがある場合は、それらを修正してからこの後の作業に進みます。Railscastsのコードはテストがすべて成功したので、引き続きアップグレード作業に移ります。

アップグレード

サイトのアップグレード作業を開始する準備ができました。これを、rails31という名前の新しいGitブランチを作成してその中で行うことにします。

$ git checkout -b rails31

Rails 3.1へのアップグレードは至ってシンプルです。ただ単にアプリケーションのGemfileを開いて、バージョン番号を3.1の最新リリース(現時点では3.1.0)に変更します。

/Gemfile

gem "rails", "3.1.0"

bundle updateを実行して新バージョンをインストールします。唯一もう一ヶ所修正が必要なのが設定ファイルのdevelopment.rbで、次の行を削除するかコメントアウトします。

/config/development.rb

# config.action_view.debug_rjs = true

テストを再度実行すると、すべて成功します。Railsサーバを正常に起動することもでき、ブラウザから参照できます。

サイトがrails 3.1で稼働した

Asset Pipelineを使用するためのアプリケーションの修正

Asset PipelineはRails 3.1の主な新機能のひとつですが、今回のアプリケーションでは画像ファイル、スタイルシート、JavaScriptファイルがまだ/publicディレクトリの下にあるので、その機能をまだまったく活かせていません。Asset Pipelineは完全にオプションの機能であるため、有効化させない限りはその機能は現れません。そのため、それを使うのかどうかまだわからない時点であっても、Rails 3.1へのアップグレードを思いとどまる必要はありません。アップグレードがいかに簡単かということを考えたら、それを今行わない理由はありません。

もしAsset Pipelineの機能を使いたければ、有効化する必要があります。そのためには次の行をGemfileに追加します。(これらの行は、新規にRails 3.1アプリケーションを作成したときに生成されるGemfileに入っています。)

/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のコードの以下の部分:

/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)

を以下のように書き換えます。

/config/application.rb

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クラスの中に次のコードを追加します。

/config/application.rb

# 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を有効化するよう設定します。

/config/environments/development.rb

  # Do not compress assets
  config.assets.compress = false
  
  # Expands the lines which load the assets
  config.assets.debug = true

次にproduction.rbを変更します。

/config/environments/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)ではアセットを圧縮したいのですが、compilefalseに設定して、プリコンパイル時にはAsset Pipelineが機能しないようにします。またdigesttrueに設定して、アセットのURLがfingerprintされるようにしました。もちろん、作成するアプリケーションが本番モードでどう振舞ってほしいかに合わせて、これらのオプションを違うように設定することも可能です。

最後にテスト環境を修正します。ここではオプションを追加して、静的なアセットが返されキャッシュされるようにして、かつasset debuggingを有効化します。

/config/environments/test.rb

# 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のキャッシュは不要だからです。

/.gitignore

.sass-cache/

アセットを移動する

Asset Pipelineが設定できたので、app/assetsディレクトリを作成します。そしてimagesjavascriptsstylesheetsの各ディレクトリを/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.jsjquery.min.jsrails.jsは削除します。ここで、エピソード279[動画を見る, 読む]で行ったのと同じように、jQueryプラグインなどのファイルを/lib/assets/vendor/assetsに移すかどうかを決めておくのがいいでしょう。

次にmanifestファイルを作成します。このアプリケーションにはすでにapplication.jsファイルとapplication.cssファイルがそれぞれ対応するディレクトリに存在するので、新たに作成する必要はありません。ではCSSファイルから始めることにします。これをmanifestファイルにするために、最初の部分にコメントを追加してSprocketsに対してどのファイルをインクルードするかを指示します。(Sprocketsの記法についてもエピソード279で紹介しました。)Sprocketsに対して、そのファイルの残りの部分と、stylesheetsディレクトリとそのサブディレクトリ以下のその他のすべてのファイルをインクルードするように指示します。

/app/assets/stylesheets/application.css

/*
*= require_self
*= require_tree .
*/

/* rest of file omitted */

application.jsファイルについても同じように指示できますが、ここではjQueryをインクルードしたいので、少し違う方法で行います。

/app/assets/javascripts/application.js

//= require jquery
//= require jquery_ujs
//= require_self
//= require_tree .

/* rest of file omitted */

ここでも、ファイル自体にコードが含まれるのでrequire_selfを追加し、同じディレクトリの他のファイルがインクルードされるようrequire_treeを追加します。

またアプリケーションのレイアウトファイルを開いてstylesheetファイルとJavaScriptファイルをインクルードしている行を修正して、関連するapplicationファイルだけを参照するようにします。というのも、その他のファイルはmanifestを介してインクルードされるからです。

/app/views/layouts/application.html.erb

<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application", "http://cdn.sublimevideo.net/js/3s7oes9q.js" %>

アプリケーションが必要とするJavaScriptファイルには、Asset Pipelineを介して読み込まれない外部ファイルも含まれます。この場合もやはり上のファイルのリストに含む必要があります。

ではここでブラウザからアプリケーションを見てみて、変更点がうまく動いているか確認します。その前にbundleを再度実行して、追加したgemをインストールします。インストールが完了したらサーバを起動します。

$ rails s

ほとんどはうまくいきますが、一部の画像、例えば画面上部のロゴが正しく表示されません。

サイトは正常に動作するが、一部の画像が表示されない

この問題の原因は、画像のURLがレイアウトファイルに直書きされていることにあります。

/app/views/layouts/application.html.erb

<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オプションを有効化すると、名前の後ろにハッシュ値が追加され、それによってファイルへの静的な参照は機能しなくなります。代わりに常にヘルパーメソッドを使用するようにします。これで、開発モードと本番モードの両方で画像に正しくリンクが貼られます。

/app/views/layouts/application.html.erb

<%= image_tag("railscasts_logo.png", :size => "423x56", :alt => "RailsCasts - Ruby on Rails Screencasts") %>

アプリケーション全体で検索して、静的に参照されているアセットすべてについて、上の画像のようにヘルパーメソッドを使用するよう修正します。ページを再度読み込むと画像が表示されるので、Asset Pipelineが正しく機能していることがわかります。

これでアプリケーションをRails 3.1にアップグレードする作業は終わりです。他にも便利な新機能がいくつかあるので、自分のアプリケーションの役に立つかどうかを確認するためにRails 3.1に関する他のエピソードも見てみることをお勧めします。