Rails 2.2には多くの新機能と機能改善が盛り込まれています。このリストは主要なアップグレードをカバーしていますが、小さなバグフィックスや変更までは含まれていません。すべての変更を見るには、GitHubのRailsメインリポジトリのコミットリストを参照してください。
Rails 2.2のリリースに伴い、現在進行中のRails Guides hackfestの最初の成果であるRails Guidesが発表されました。Rails Guidesでは、Railsの主要な機能に関する高品質なドキュメントを提供する予定です。
Rails 2.2は、Railsを安定稼働させ、世界とつなぐインフラストラクチャとして重要なリリースです。
Rails 2.2では、国際化(internationalization: 長いのでi18nと略されます)向けの簡単なシステムが提供されます。
RailsがJRubyや次期Ruby 1.9とスレッド安全性に関してうまく動作するよう、多くの作業が行われました。Ruby 1.9のリリースはまだ先なので、Ruby 1.9でRailsを動かすのはまだ難しい状態ですが、Ruby 1.9がリリースされたときにRailsが移行する準備は整っています。
コードコメント形式のRails内部ドキュメントが随所で改善されました。また、Railsガイドプロジェクトは、Railsの主要なコンポーネントに関する決定的な情報源です。最初の公式リリースにはRailsガイドの以下のページが含まれています。
このガイドには、初級および中級Rails開発者向けの数万語におよぶガイドが用意されています。
ガイドをローカルで生成したい場合は、アプリケーションのディレクトリで以下を実行します。
$ rake doc:guides
これでガイドがRails.root/doc/guides
以下に生成され、ブラウザでRails.root/doc/guides/index.html
を開けばすぐに内容を表示できます。
HTTPヘッダでETagと最終更新タイムスタンプをサポートしたことで、最近更新されていないリソースへのリクエストをRailsが受け取ったときに空のレスポンスを返せるようになりました。これにより、レスポンスの送信が不要かどうかを確認できます。
class ArticlesController < ApplicationController def show_with_respond_to_block @article = Article.find(params[:id]) # リクエストで送信するヘッダがstale?に提供されたオプションと異なる場合、 # リクエストは実際にstaleし、respond_toブロックが起動する # (このときstale?呼び出しのオプションがレスポンスにセットされる)。 # リクエストヘッダがマッチする場合リクエストはフレッシュなのでrespond_toブロックはトリガーされない。 # 代わりにデフォルトのレンダリングが発生してlast-modifiedとetagヘッダーをチェックし、 # テンプレートをレンダリングする代わりに "304 Not Modified" だけを送信すればよいと判断する。 if stale?(:last_modified => @article.published_at.utc, :etag => @article) respond_to do |wants| # normal response processing end end end def show_with_implied_render @article = Article.find(params[:id]) # レスポンスヘッダを設定し、リクエストに対してそれらをチェックする。 # リクエストがstaleの場合(すなわちetagまたはlast-modifiedのいずれもマッチしない場合)、 # デフォルトのテンプレートレンダリングが行われる。 # リクエストがフレッシュな場合、デフォルトレンダリングはテンプレートをレンダリングする代わりに # "304 Not Modified "を返す。 fresh_when(:last_modified => @article.published_at.utc, :etag => @article) end end
Railsをスレッドセーフにするために行われた作業がRails 2.2に反映されています。Webサーバのインフラにもよりますが、これはメモリ内のRailsのコピー数が少なくても、より多くのリクエストを処理できることを意味し、サーバのパフォーマンス向上とマルチコアの利用率向上につながります。
アプリケーションのproductionモードでマルチスレッドディスパッチを有効にするには、config/environments/production.rb
に以下の行を追加してください。
config.threadsafe!
ここでは、「トランザクショナルマイグレーション」と「プールされたデータベーストランザクション」という、2つの大きな追加機能について説明します。また、joinテーブル条件向けの新しい(そしてよりきれいな)構文の導入や、多くの小さな改良も行われました。
歴史的に、ステップを複数含むRailsマイグレーションはトラブルの元でした。マイグレーション中に何か問題が発生すると、エラー発生前のマイグレーションはデータベースを変更しますが、エラー発生後のマイグレーションは適用されません。また、マイグレーションのバージョンは実行済みとして保存されていたので、問題を解決した後にrake db:migrate:redo
で単純に再実行できませんでした。トランザクショナルマイグレーションは、マイグレーションステップをDDLトランザクションでラップすることでこれを変更し、どれかが失敗したらマイグレーション全体を元に戻すようにします。Rails 2.2では、トランザクショナルマイグレーションは、PostgreSQLですぐにサポートされます。将来このコードは他のデータベースにも拡張可能で、IBMはすでにDB2アダプタをサポートするよう拡張しています。
コネクションプーリングは、Railsがデータベース接続のプールにデータベースリクエストを分散させ、最大サイズまで成長させられます(デフォルトでは5ですが、database.yml
にpool
キーを追加すれば調整できます)。これは、同時に多数のユーザーをサポートするアプリケーションのボトルネックを解消するのに役立ちます。また、wait_timeout
も用意されており、デフォルトでは5秒で終了します。ActiveRecord::Base.connection_pool
は、必要に応じてプールに直接アクセスできます。
development: adapter: mysql username: root database: sample_development pool: 10 wait_timeout: 10
joinテーブル条件をハッシュで指定できるようになりました。これは、複雑なjoinをまたいでクエリを実行する必要がある場合に非常に有用です。
class Photo < ActiveRecord::Base belongs_to :product end class Product < ActiveRecord::Base has_many :photos end # 著作権フリーのproductをすべて取得する Product.all(:joins => :photos, :conditions => { :photos => { :copyright => false }})
Active Recordの動的finderファミリーに、新たに2つのメソッドが追加されました。
find_last_by_attribute
find_last_by_attribute
メソッドは、Model.last(:conditions => {:attribute => value})
と同等です。
# ロンドンからサインアップした直近のユーザーを取得する User.find_last_by_city('London')
find_by_attribute!
!
付きの新しいfind_by_attribute!
は、Model.first(:conditions => {:attribute => value}) || raise ActiveRecord::RecordNotFound
と同等です。マッチするレコードが見つからない場合は、nil
を返す代わりに例外を発生します。
# 'Moby'がサインアップしていなければActiveRecord::RecordNotFound例外を発生する User.find_by_name!('Moby')
Active Recordの関連付けプロキシは、プロキシされたオブジェクトのメソッドのスコープを尊重するようになりました。以前の@user.account.private_method
は、関連付けられたAccountオブジェクトのprivateメソッドを呼び出していました(User has_one :account
の場合)。この機能が必要な場合は、@user.account.send(:private_method)
をお使いください(または、メソッドをprivateやprotectedではなくpublicにしてください)。method_missing
をオーバーライドしている場合は、関連付けが正常に機能するようにrespond_to
も同じ挙動になるようにオーバーライドする必要がある点にご注意ください。
rake db:migrate:redo
にオプションでVERSIONを追加することで、redoで特定のマイグレーションを指定可能になりました。config.active_record.timestamped_migrations = false
と設定してください。:counter_cache => true
で宣言された関連付け)をゼロに初期化する必要がなくなりました。ActiveRecord::Base.human_name
により、国際化に対応したモデル名を人間に読みやすく翻訳できるようになりました。コントローラ側では、ルーティングを整理するのに役立ついくつかの変更があります。また、複雑なアプリケーションのメモリ使用量を減らすために、ルーティングエンジンの内部にもいくつかの変更が加えられています。
ルーティングの「浅いネスト」は、ネストの深いリソースを使うときのよく知られた問題に対するソリューションを提供します。浅いネストでは、作業したいリソースを一意に識別するのに十分な情報だけを提供すれば済むようになりました。
map.resources :publishers, :shallow => true do |publisher| publisher.resources :magazines do |magazine| magazine.resources :photos end end
これで、以下のルーティングが認識されるようになります。
/publishers/1 ==> publisher_path(1) /publishers/1/magazines ==> publisher_magazines_path(1) /magazines/2 ==> magazine_path(2) /magazines/2/photos ==> magazines_photos_path(2) /photos/3 ==> photo_path(3)
新しいmemberルーティングやcollectionルーティングに対して、メソッドの配列を指定できるようになりました。これにより、複数のHTTP verbを処理する必要があるときに、任意のverbを受け取るようにルーティングを定義しなければならないという煩わしさから解放されます。以下はRails 2.2で有効なルート宣言です。
map.resources :photos, :collection => { :search => [:get, :post] }
デフォルトでは、map.resources
を使ってルートを作成すると、Railsは7つのデフォルトアクション(index, show, create, new, edit, update, and destroy)に対するルーティングを生成します。しかし、これらのルーティングはそれぞれアプリケーションのメモリを消費し、Railsが追加のルーティングロジックを生成することになります。そこで、:only
と:except
オプションを使って、Railsがリソースに対して生成するルートを細かく設定できるようになりました。単一のアクション、アクションの配列、または特殊オプション:all
や:none
を指定できます。これらのオプションは、ネストしたリソースに継承されます。
map.resources :photos, :only => [:index, :show] map.resources :products, :except => :destroy
config.action_controller.use_accept_header = true
でオンに戻せます。redirect_to
がURIスキームを完全にサポートしました(たとえばssh: URI
にリダイレクトできます)。render
が:js
オプションをサポートし、正しいMIMEタイプを持つ素のJavaScriptをレンダリングするようになりました。polymorphic_path([@project, @date, @area])
をnilの日付で呼ぶと、project_area_path
が返されます。javascript_include_tag
とstylesheet_link_tag
が新しい:recursive
オプションをサポートし、:all
も指定することでファイルのツリー全体を読み込めるようになりました。RJS#page.reload
は、ブラウザの現在のページをJavaScriptで再読み込みします。atom_feed
ヘルパーに:instruct
オプションが追加され、XML処理命令を挿入できるようになりました。Action Mailerがメーラーでレイアウトをサポートするようになりました。適切な名前のレイアウトを指定すると、HTMLメールをブラウザ上のビューのように整形できます。たとえば、CustomerMailer
クラスはlayouts/customer_mailer.html.erb
を使うことを想定しています。
Action Mailerは、GMailのSMTPサーバーでSTARTTLSを自動的にオンにすることで、ビルトインのサポートを提供するようになりました。このためには、Ruby 1.8.7がインストールされている必要があります。
Active Supportは、Railsアプリケーションのメモ化機能の組み込み、each_with_object
メソッド、委譲でのプレフィックスサポートなど、多くの新しいユーティリティメソッドを提供するようになりました。
メモ化(memoization)とは、あるメソッドを一度初期化した後、その値を保存して繰り返し使えるようにする手法です。自分のアプリケーションでこのパターンを使ったことがある人も多いでしょう。
def full_name @full_name ||= "#{first_name} #{last_name}" end
メモ化を使うと、このタスクを宣言的に処理できます。
extend ActiveSupport::Memoizable def full_name "#{first_name} #{last_name}" end memoize :full_name
その他のメモ化機能には、メモ化をオンオフできるunmemoize
, unmemoize_all
, memoize_all
などがあります。
each_with_object
each_with_object
メソッドは、Ruby 1.9からバックポートされたメソッドを用いてinject
の代替となるメソッドを提供します。これはコレクションに対して反復処理を行い、現在の要素とメモをブロックに渡します。
%w(foo bar).each_with_object({}) { |str, hsh| hsh[str] = str.upcase } # => {'foo' => 'FOO', 'bar' => 'BAR'}
リードコントリビュータ: Adam Keys
あるクラスから別のクラスに振る舞いを委譲する場合、委譲されるメソッドで以下のようにプレフィックスを指定できるようになりました。
class Vendor < ActiveRecord::Base has_one :account delegate :email, :password, :to => :account, :prefix => true end
上はvendor#account_email
とvendor#account_password
という委譲メソッドを生成します。また、以下のようにカスタムのプレフィックスも指定できます。
class Vendor < ActiveRecord::Base has_one :account delegate :email, :password, :to => :account, :prefix => :owner end
上はvendor#owner_email
およびvendor#owner_password
という委譲メソッドを生成します。
リードコントリビュータ: Daniel Schierbeck
ActiveSupport::Multibyte
が大幅に更新されました。Ruby 1.9との互換性のための修正も含まれます。ActiveSupport::Rescuable
が追加され、任意のクラスがrescue_from
構文にミックスインできるようになりました。Date
とTime
クラスにpast?
, today?
, future?
が追加され、日付や時間を比較しやすくなりました。Array#[1]
〜Array#[4]
までのエイリアスとしてArray#second
〜Array#fifth
が追加されました。Enumerable#many?
はcollection.size > 1
をカプセル化したものです。Inflector#parameterize
は、入力をURLで利用可能な形に変換します(to_param
で使われます)。1.7.weeks.ago
や1.5.hours.since
のように認識できるようになりました。ActiveSupport::StringInquirer
は、文字列が等しいかどうかをスマートにテストする方法を提供します(ActiveSupport::StringInquirer.new("abc").abc? => true
)。Railties(Railsのコアコード)で最も大きな変更は、config.gems
の仕組みです。
config.gems
Railsアプリケーションで必要なすべてのgemsのコピーを/vendor/gems
に配置可能にすることで、デプロイの問題を回避し、Railsアプリケーションを自己完結性を高められるようになりました。この機能はRails 2.1で初めて登場しましたが、Rails 2.2ではより柔軟で堅牢になり、gems間の複雑な依存関係も扱えるようになりました。RailsのGem管理では以下のコマンドが使えます。
config.gem _gem名_
: config/environment.rb
ファイルに対応するgemを設定rake gems
: 設定済みのgemをすべて表示する。gem(および依存関係が)インストール済みか、frozenか、フレームワークgemかも表示されます(フレームワークgemは他のgemが実行されるよりも先に読み込まれ、frozenにできない)。rake gems:install
: インストールされていないgemをインストールするrake gems:unpack
: 必須gemのコピーを/vendor/gems
に配置するrake gems:unpack:dependencies
: 必須gemのコピーと依存関係を/vendor/gems
に配置するrake gems:build
: ビルドされていないネイティブ拡張をビルドするrake gems:refresh_specs
: Rails 2.1で作成されたベンダリングgemをRails 2.2の保存方法に変える単一のgemをunpackまたはインストールする場合は、コマンドラインでGEM=_gem名_
を指定します。
script/server
がThinを直接サポートするようになりました。script/plugin install <plugin> -r <revision>
がsvnベースのプラグインと同様にgitベースのプラグインでも動作するようになりました。script/console
で--debugger
オプションがサポートされました。rake notes:custom ANNOTATION=MYFLAG
でカスタムアノテーションをリストアップできます。Rails.env
がStringInquirer
でラップされ、Rails.env.development?
が使えるようになりました。今回のリリースで、一部の古いコードが非推奨化されました。
Rails::SecretKeyGenerator
はActiveSupport::SecureRandom
に置き換えられました。render_component
は非推奨化されました。この機能が必要な場合はrender_components pluginを利用できます。パーシャルをレンダリングするときの暗黙のローカル代入が非推奨化されました。
def partial_with_implicit_local_assignment @customer = Customer.new("Marcel") render :partial => "customer" end
以前は、上記のコードで'customer'パーシャル内のcustomer
というローカル変数が利用可能でした。現在は、すべての変数を明示的に:locals
ハッシュで渡す必要があります。
country_select
が削除されました。詳細および代替プラグインについては、http://www.rubyonrails.org/deprecation/list-of-countriesを参照してください(訳注: このページは現在無効です)。
ActiveRecord::Base.allow_concurrency
は無効になりました。
ActiveRecord::Errors.default_error_messages
は非推奨化されました。I18n.translate('activerecord.errors.messages')
をお使い下さい。
%s
と%d
の式展開構文は国際化で非推奨化されました。
String#chars
は非推奨化され、代わりにString#mb_chars
が採用されました。
小数で表される月や年の長さが非推奨化されました。代わりに、RubyコアのDate
クラスやTime
クラスの演算をお使いください。
Request#relative_url_root
は非推奨化されました。代わりにActionController::Base.relative_url_root
をお使いください。
リリースノート編集担当:Mike Gunderloy
Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。
原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨
本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。
Railsガイド運営チーム (@RailsGuidesJP)
Railsガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。