Ruby on Rails 2.3 リリースノート
いつものように意訳.たぶんここを見た方がいいような気もします.
Rails 2.3 には数多くの新しい機能が含まれている.Rack への対応や Rails エンジンの一新,Active Record ではトランザクションのネストやスコープ,レンダリングの統一や効率的なルーティング,そしてアプリケーションテンプレートと静かなバックトレース.本記事のリストは,メジャーアップグレードの内容をカバーしているが,細かな変更やバグフィックスは記載していない.もしすべてを知りたいときは,Commit ログか CHANGELOG を見てほしい.
アプリケーションアーキテクチャー
Rails アプリケーションのアーキテクチャーについて2つの大きな変更がある.Rack への対応と Rails エンジンに対する新しいサポートである.
Rack への対応
Rails は,いまや CGI の過去を破壊してすべての場面で Rack を使うようになった.これには莫大な数の内部変更を伴った(ただしもし CGI を使うときも心配しなくてもいい.Rails はプロキシーインターフェイスを通じて CGI をサポートしている).まだこれは Rails 内部への大きな変更であるので,2.3 へアップグレードしたのちには,ローカル環境と Production 環境でテストする必要がある.テストすべき点は下記のとおりだ.
以下に Rack に関わる変更点をまとめておく.
- script/server は Rack を使うように変更されたので,Rack 互換のどんなサーバをもサポートするようになった.script/server はまた rackup 設定ファイルがあればそれを参照するようになる.デフォルトでは,config.ru ファイルを探し,-c オプションで指定可能だ.
- FCGI handler は Rack を通じて
- ActionController::Dispatcher はそのデフォルトのミドルウェアスタックを維持する.ミドルウェアは inject されるか整理されるか削除されるだろう.スタックは起動処理中にコンパイルされる.envrionment.rb でミドルウェアスタックを構成することができる.
- ミドルウェアスタックを調査するための Rake タスクが追加された.ミドルウェアスタックの順序をデバッグするのに役に立つ.
- 統合テストがミドルウェアとアプリケーションスタック全体に対して実行するように変更された.これは統合テストを Rack ミドルウェアのテストを万全のものとする.
- ActionController::CGIHandler は Rack での CGI ラッパーと後方互換性がある.CGIHandler は古い CGI オブジェクトとその環境情報を Rack 形式に変換する.
- CgiRequest と CgiResponse は削除された
- Session store が Lazy Loadingになった.もし session を使わない場合は,session データを読み込むことはない.(cookie を parse したり,memcache からデータを取得したり,Active Record オブジェクトを探したりしない)
- CGI::Session::CookieStore は ActionController::Session::CookieStore に変更された.
- CGI::Session::MemCacheStore が ActionController::Session::MemCacheStore に変更された.
- CGI::Session::ActiveRecordStore が ActiveRecord::SessionStore に変更された.
- session store を
ActionController::Base.session_store = :active_record_store
に変更することもまだできる.
- デフォルトのセッションオプション指定もまだ,
ActionController::Base.session = { :key => "..." }
の形式のまま.
- mutex はミドルウェア ActionController::Lock に移動した.
- ActionController::AbstractRequest と ActionController::Request は統合された.新しい ActionController::Request は Rack::Request を継承している.これはたとえば response.headers[type] ではなく,response.content_type を使うなどの影響を与える.
- ActiveRecord::QueryCache ミドルウェアは ActiveRecord がロードされた場合には自動的にミドルウェアスタックに入るようになっている.このミドルウェアは Active Record のクエリーキャッシュを制御する.
- Rails のルーティングと controller クラスは Rack の仕様に従うので,SomeController.call(env) のように直接呼び出せるようになり,ルーティングパラメータは rack.routing_args に保存される.
- ActionController::Record は Rack::Request を継承する.
- config.action_controller.session は
config.action_controller.session = {:session_key => foo}
ではなく
config.action_controller.session = {:key => foo}
を使うようになる.
ドキュメント
Ruby on Rails ガイドプロジェクトは Rails 2.3 についてのガイドを追加した.加えて別のサイトで Edge Rails のガイドも立ち上げた.Rails wiki の再開と早い段階での Rails 本の計画が計画されている.
Active Record
Rails 2.3 では,Action Record に多くの新機能が追加され,また多くのバグフィックスが行われた.目立ったところでは,属性指定とトランザクションのネスト対応,動的スコープとデフォルトスコープがある.
属性のネスト対応
Active Record はネストしたモデルの属性を直接扱うことができるようになった.
class Book < ActiveRecord::Base has_one :author has_many :pages accepts_nested_attributes_for :author, :pages end
ネストした属性は様々な恩恵をもたらす.関連モデルと一緒に(原子的に)保存できたり,関連モデルからの検証,関連モデル一括でのフォーム(後述する)など.
ネストしたトランザクション
Active Record は多くの要望があったネストしたトランザクションに対応する.
User.transaction do User.create(:username => 'Admin') User.transaction(:requires_new => true) do User.create(:username => 'Regular') raise ActiveRecord::Rollback end end User.find(:all) # => :username => 'Admin' だけが返る
ネストしたトランザクションは,外側のトランザクションの状態に影響を与えること無く,内部のトランザクションのみロールバックさせることができる.もしトランザクションをネスト化したいときは,明示的に :requires_new オプションを追加すればいい.そうでなければ,ネストしたトランザクションは親トランザクションの一部になる(現在の Rails 2.2 と同様).ネスト化したトランザクションは savepoint を使うので,データベースがネスト化したトランザクションをサポートしていなくても動作する.またテストのときに,トランザクション用のフィクスチャーがうまく動作するような小さな魔法もある.
動的スコープ
Rails での動的検索(find_by_color_and_flavor のようなメソッドをでっち上げる機能)と named_scope(再利用可能なクエリー条件をカプセル化して名前をつけられる機能) は知っているだろう.動的スコープはメソッドチェーンでフィルタリングできる構文だ.例えば,
Order.scoped_by_customer_id(12) Order.scoped_by_customer_id(12).find(:all, :conditions => "status ='open'") Order.scoped_by_customer_id(12).scoped_by_status("open")
scopes: で定義しなくても動的にスコープを使うことができる.
デフォルトスコープ
Rails 2.3 は named_scope のようなデフォルトのスコープを導入する.これはすべての named_scope と find メソッドに適用される.例えば
default_scope :order => "name ASC"
とすると,いつでも name でソートした結果が得られる(もちろん上書きすればそうではないが)
- 開発者:Pawe〓 Kondzior
- 参考:What’s New in Edge Rails: Default Scoping
コールバックの多重条件
Active Record のコールバックを使うとき,:if/:unless を同じコールバックに同時に使うことができるようになった.
また複数の条件を Array で渡すことができるようになった.
before_save :update_credit_rating, :if => :active, :unless => [:admin, :cash_only]
- 開発者:L. Caviola
HAVING 付きの find
Rails は find メソッドで :having を扱えるようになった(has_may や has_and_belongs_to_many でも同様).これはグループ化によるフィルタリングを可能にする.
developers = Developer.find(:all, :group => "salary", :having => "sum(salary) > 10000", :select => "salary")
has_many での Hash 指定
has_many で条件を Hash で指定できるようになった.
has_many :orders, :conditions => {:status => 'confirmed'}
これは Rails 2.1 では動作していたが,Rails 2.2 では動かなくなっていた.そして Rails 2.3 で復活した(Rails 2.1 では Hash ではなく String).
- 開発者:Frederick Cheung
MySQL接続への再接続
MySQL はその接続において再接続フラグをサポートしている.これが true だと,クライアントは前の接続が切断される前にサーバへ再接続を試みる.Rails 2.3 ではこれを設定することができるようになった.デフォルトでは false なので,既存のアプリへの影響はない.
他の Active Record 周りの変更
- has_and_belongs_to_many の場合の余分な AS (alias)を削除した.
- ActiveRecord::Base#new_record? は既存レコードの場合に,nil ではなく false を返すようになった.
- has_many :through でのテーブル名クォートのバグが解消された.
- updated_at の値を指定できるようになった.
cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago)
Action Controller
今回のリリースでは,Action Controller におけるレンダリングに関する変更は,ルーティングや他の変更と同じぐらい重要なものとなっている.
統一されたレンダリング
ActionController::Base#reder は何をレンダリングするかをスマートに決定するようになった.何をレンダリングするか指示すれば,それが正しく返る.Rails 2.3 以前は,render する情報を明確に与える必要があった.
render :file => '/tmp/random_file.erb' render :template => 'other_controller/action' render :action => 'show'
Rails 2.3 では,何をレンダリングしたいかを指示するだけでいい.
render '/tmp/random_file.erb' render 'other_controller/action' render 'show' render :show
Rails はファイル・テンプレート・アクションを,引数のスラッシュなどから何をレンダリングすべきかを選択する.アクションの場合は String ではなく Symbol も使える.古い形式も使えるが,明示的にオプションを指定しなければならない.
Application Controller の名前変更
もし application.rb だけ特別なネーミングなので困っていたのなら喜んでほしい.Rails 2.3 では application_controller.rb に変更される.加えて,rake rails:update:application_controller という新しい rake task が追加されるので,これを使って自動的に名前を変更できる.これは rails:update の処理の一部だ.
HTTP Digest Authentication のサポート
Rails 2.3 から HTTP digest Authentication をサポートする.利用するには authenticate_or_request_with_http_digest をユーザのパスワードを返すようなブロック付きで呼び出せばいい.(パスワードはハッシュ化されていて,クレデンシャルと比較されている.)
class PostsController < ApplicationController Users = {"dhh" => "secret"} before_filter :authenticate def secret render :text => "Password Required!" end private def authenticate realm = "Application" authenticate_or_request_with_http_digest(realm) do |name| Users[name] end end end
より効率的なルーティング
Rails 2.3 では重要なルーティングの変更が2つある.まず :format オプションの解析を止められるようになった.これにより,ルートの生成処理が 50% 削減された.その結果かなりの量のメモリを削減できた(大きなアプリだと 100MB 程度).もし format helper を使っているなら,また使うことはできるのだが,そのうち使えなくなるし,新しく書き換えることでアプリケーションはより効率的に動作するようになる.もう一つの大きな変更は,複数のルーティングファイルのサポートだ.RouteSet#add_configuration_file を使うことで,同時により多くのルートファイルを扱うことができる.既に読み込まれたルート情報をクリアしなくても大丈夫.この変更は Engine にとってはかなり有用である一方,アプリケーションで使うにはバッチでルートファイルを読み込む必要がある.
- 開発者:[:title=Aaron Batalion]
Rack ベースの遅延ロードセッション
Action Controller の session ストレージが Rack レベルまで押し下げられた.これはかなりのコードの変更があったが,Rails アプリからは完全に透過な状態となっている*2(ボーナスとして,時代遅れの CGI セッションのパッチが削除された).これは重要だが一つの単純な理由による.それは Rails ではない Rack アプリが同じセッションを見れるようにするためだ.加えて,セッションが遅延ロードされることになった(in line with the loading improvements to the rest of the framework).つまりセッションを使わないときに明示的に disable にする必要がなくなったということだ.参照しなければ,ロードもされない.
MIME タイプの処理方法変更
Rails 2.3 では,MIME 処理方法について2つの変更がある.
最初は MIME::Type に =~ 演算子を導入して,検証をよりわかりやすくできるようにした.
if content_type && Mime::JS =~ content_type # do something cool end Mime::JS =~ "text/javascript" => true Mime::JS =~ "application/javascript" => true
もう一方の変更は,JavaScript の検出に Mime::JS を使うようになったことだ.
- 開発者:Seth Fitzsimmons
respond_to の最適化
Rails-Merb チームの合流による最初の果実は,Rails 2.3 が respond_to の最適化を含んでいることだろう.それはもちろんリクエストの MIME 型に応じて結果を整形することができる,多くの Rails アプリケーションで使われている.method_missing の呼び出しを削除,プロファイリングと微調整により,3種類のフォーマットを切り替える respond_to への単純な呼び出しのパフォーマンスが 8% 向上した.いいところは?アプリ側のコードを書き換えること無く,高速化できることだ.
キャッシュパフォーマンスの改善
Rails 2.3 ではリクエストごとのローカルキャッシュを保存するようになった.不必要な読み込みを抑え,サイトのパフォーマンスを向上させる.当初は MemCacheStore に限定されていたが,必要なメソッドが実装されているあらゆる保存先を選べるようになった.
- 開発者:Nahum Wild
Viewのローカライズ
Rails 2.3 では,迫っていされた locale に応じて,ローカライズされた View を表示できる.例えば,Posts controller に show action があるしよう.デフォルトでは,app/views/posts/show.html.erb をレンダリングする.もし I18n.locale = :da と設定すれば,app/views/posts.show.da.html.erb をレンダリングするようになる.ローカライズされたテンプレートが無い場合は,デフォルトのものが使われる.Rails に I18n#available_locales と I18n::SimpleBackend#available_locales が追加され,有効な locale の Array が帰ってくる.
その他の Action Controller の変更
- ETag 処理を少しだけ整理した.Rails 2.3 は response body が無いか send_file でファイルを送信するときには,ETag ヘッダーをスキップするようになった.
- 携帯サイトのプロキシーは一般的に正しく設定されていないので,Rails が IP spoofing をチェックする事実は厄介なものになる.そんなときは,ActionController::Base.ip_spoofing_check = false に設定すれば,チェックを無効にできる.
- ActionController::Dispatcher はミドルウェアスタックとして実装された.rake middleware でそれを見ることができる.
- サーバ側の保存との API 互換性のために,Cookie セッションが永続的なセッション識別子を持つようになった.
- 以下のように,send_data/send_fila のオプションに Symbol を設定可能となった.
send_file("fabulous.png", :type => :png)
- map.resources では,:only/:except はネストしたりソースには継承されなくなった.
Action View
Rails 2.3 の Action View はネストされたモデルのモームや,レンダリングの改善,
日付選択ヘルパーのフレキシブルな表示,そしてキャッシュの高速化などがある.
ネストされたモデルのフォーム
(Active Record の項目で議論したが)親モデルが子モデルの属性を受け取ることができるので,form_for や field_for を使ってネストしたフォームを作成することができる.このフォームは任意の深さまでネストすることができ,少ないコードで複雑なヒエラルキーのフォームを扱うことができる.例えば次のような場合,
class Customer < ActiveRecord::Base has_many :orders accepts_nested_attributes_for :orders, :allow_destroy => true end
Rails 2.3 では View を以下のように書くことができる.
<% form_for @customer do |customer_form| %> <div> <%= customer_form.label :name, 'Customer Name:' %> <%= customer_form.text_field :name %> </div> <!-- Here we call fields_for on the customer_form builder instance. The block is called for each member of the orders collection. --> <% customer_form.fields_for :orders do |order_form| %> <p> <div> <%= order_form.label :number, 'Order Number:' %> <%= order_form.text_field :number %> </div> <!-- The allow_destroy option in the model enables deletion of child records. --> <% unless order_form.object.new_record? %> <div> <%= order_form.label :_delete, 'Remove:' %> <%= order_form.check_box :_delete %> </div> <% end %> </p> <% end %> <%= customer_form.submit %> <% end %>
スマートな partial レンダリング
render メソッドは旧来に比べてかなりスマートになった.もしオブジェクトかコレクションと適切な partial template があって,その名前がマッチしていれば,オブジェクトなどを適切にレンダリングできる.例えば Rails 2.3 では次の用に書ける.
render @article # Equivalent of render :partial => 'articles/_article', :object => @article render @articles # Equivalent of render :partial => 'articles/_article', :collection => @articles
日付選択ヘルパーのプロンプト
Rails 2.3 では様々な日付選択ヘルパーの表示を,select に配列を渡したときと同じようにカスタマイズできる.プロンプトを,文字列や複数の属性があるときには Hash で指定できる.また :prompt に true を設定すれば,一般的な :prompt を使うことができる.
select_datetime(DateTime.now, :prompt => true) select_datetime(DateTime.now, :prompt => "Choose date and time") select_datetime(DateTime.now, :prompt => {:day => 'Choose day', :month => 'Choose month', :year => 'Choose year', :hour => 'Choose hour', :minute => 'Choose minute'})
- 開発者Sam Oliver
AssetTag のタイムスタンプキャッシュ(AssetTag Timestamp Caching)
キャッシュを使わないようにするために URL にタイムスタンプを追加したりするのはよくある.これにより,サーバ上で画像やスタイルシートなどを変更した際,ブラウザにキャッシュを使わずにサーバからデータを取得させることができる.Rails 2.3 ではこの振る舞いを Action View の cache_asset_timestamps で変更することができる.もしキャッシュを有効にすれば,Rails はそのリソースを最初にアクセスした時間を計算し,その時間を保存する.これは静的ファイルは少数しかサーバから配信されないことを意味する.しかしこれはまた,サーバの動作中はリソースを変更できないということであり,クライアントが変更を取得できないということである.
ホストをオブジェクトとして扱う
Edge Rails ではよりフレキシブルにレスポンスを返すホストを定義することができるようになった.これはホスト資源に応じて選択ロジックを実装することができる.
grouped_options_for_select ヘルパー
いままでも select タグのための多くのヘルパーがあったが,今回もう一つ grouped_options_for_select が追加された.
これは String の Hash や Array を受け取って optgroup/option タグを生成してくれる.
例えば,
grouped_options_for_select([["Hats", ["Baseball Cap","Cowboy Hat"]]], "Cowboy Hat", "Choose a product...")
は
<option value="">Choose a product...</option> <optgroup label="Hats"> <option value="Baseball Cap">Baseball Cap</option> <option selected="selected" value="Cowboy Hat">Cowboy Hat</option> </optgroup>
となる.
その他の Action View の変更
- CSRF 対策のトークン生成がよりシンプルになった.セッションIDをどうこうするよりも,ActiveSupport::SecureRandom により生成されるシンプルなランダムも字列を使う.
- auto_link は,e-mail リンクを生成するのに適切に(:target/:class のような)オプションを適用するようになった.
- auto_link ヘルパーが綺麗に直感的にリファクタリングされた.
Active Support
Active Support にはおもしろい変更,とくに Object#try がある.
Object#try
多くの人が try() という記法を,オブジェクトに対してメソッドを「試みる」処理として受け入れている.これは特に View で便利で,<%= @person.try(:name) -%> のように書くことで nil チェックをしなくても済む.よしこれで Rails は焼き上がった*4.ただし実装されたとしても,private メソッドは NoMethodError になるし,nil の場合はいつも nil が返る.
- 参考:try()
Object#tap のバックポート
Object#tap は Ruby 1.9 や Ruby 1.8.7 で追加されたもので,ブロックを実行し生成されたオブジェクトを返すメソッドだ.Rails 2.3 ではこれを Ruby 1.8.7 以前でも動作するようにして取り込んだ.
TimeWithZone で1秒以下を扱うように
Time/TimeWithZone クラスには時間を XML にやさしい文字列で返す xmlschema メソッドがある.
Rails 2.3 では TimeWithZone が秒以下の単位をサポートするようになった.
桁数を指定可能で,例えば以下のようになる.
>> Time.zone.now.xmlschema(6) => "2009-01-16T13:00:06.13653Z"
- 開発者:Nicholas Dainty
JSON キーのクオート
json.org で仕様を見ると,すべての JSON のキーは文字列であり,ダブルクオートで括られなければならないことがわかる.Rails 2.3 からは,数値のキーでもダブルクオートで括るようになる.
Active Support の他の変更
- ブロックでマッチした要素がないかどうかをチェックする Enumerable#none? が追加された.
- Active Support の移譲を使うとき,新しく :allow_nil オプションを使えるようになった.このオプションが設定されていると,オブジェクトが nil の場合に例外を出すのではなく, nil を返すようになる.
- ActiveSupport::OrderedHash が each_key と each_value でサポートされた.
- ActiveSupport::MessageEncryptor によってクッキーのような信頼性の低い場所に情報を保存するための,簡単な暗号化を提供する.
- Active Support の from_xml メソッドはもはや XmlSimple には依存していない.かわりに Rails は XmlMini の実装を取り込んでいる.これにより,Rails は XmlSimple が無くても動作するようになった.
Railties
前述した Rack 対応に加えて,Railties(Rails のコアの部分)にも多くの重要な変更がある.Rails Metal やアプリケーションテンプレート,静かなバックトレースなどだ.
Rails Metal
Raile Metal は Rails アプリに高速コントローラーを提供する機構である.Metal クラスはルーティングと Action Contoller の処理をパスしてスピードを稼ぐことができる.これは Rails をミドルウェアスタックとして Rack アプリケーションに対応したことによる.
アプリケーションテンプレート
Rails 2.3 は Jeremy McAnally のアプリケーションジェネレーター rgを取り込んだ.これは Rails にテンプレートベースのアプリケーションジェネレーターが導入されたと言うことだ.もしいつもアプリケーションにセットアップしているようなプラグインがあるのなら,テンプレートを1度だけ設定すれば,rails コマンドを使うときに何度でもそれを使うことができる.既存のアプリケーションにテンプレートを適用するための rake task もある.
rake rails:template LOCATION=~/template.rb
これは既存のコードの上にテンプレートの変更を重ねることになる.
- 開発者:Jeremy McAnally
- 参考:Rails templates
静かなバックトレース
Test::Unit のバックトレース部分を取り除ける Thoughtbot の Quiet Backtraceプラグインを取り込んで,Rails 2.3 は ActiveSupport::BacktraceCleaner と Rails::BacktraceCleaner をコア部分に実装した.これはフィルター(バックトレースを正規表現に従って置換する)とサイレンサー(バックトレースを完全に取り除く)の両方をサポートする.Rails は新しいアプリケーションでのもっとも一般的なノイズを取り除くためにサイレンサーを自動的に追加し,config/backtrace_silencers.rb を追加する.これによりバックトレースであらゆる gem からの表示を見やすくしてくれる*5.
遅延ロード/オートロードによる development 環境における起動の高速化
Rails(とそれに依存しているもの)の一部のみが必要になったときにメモリに読み込まれるという,極めて小さな仕事がなされた.フレームワークのコア部分(Active Support/Active Record/Action Controller/Action Mailer/Action View)はそれぞれのクラスを遅延ロードするためにオートロードが使われる.これはメモリ少量を削減し,全体的な Rails のパフォーマンスを改善する.
また(preload_frameworks オプションを使うことで)起動時にどのコアライブラリをロードするかを指定することができる.これはデフォルトでは false なので,Rails は一つずつ読み込んでいくが,1度にすべてを読み込む必要がある状況もある.たとえば Passenger/JRuby は Rails のすべてが一緒にロードされることが求められる.
他の Railties の変更
- Rails をビルドするために CI サーバをアップデートする説明を更新した.
- Rails 内部のテストを Test::Unit::TestCase から ActiveSupport::TestCase に変更し,Rails コア部分はテストに Mocha を必要としている.
- デフォルトの environment.rb が整理された.
- dbconsole スクリプトですべて数値のパスワードを使ってもクラッシュしなくなった.
- Rails.root が Pathname オブジェクトを返すので,File.join を使ってパス名部分を整理できる.
- CGI/FCGI のディスパッチで扱われる /public 以下の多くのファイルが,デフォルトでは生成されなくなった(--with-dispatches オプションで生成することができるし,rails:generate_dispatchers で追加することもできる.).
廃止予定
古いコードのいくつかがこのリリースで廃止予定となる.
- inspector/reaper/spawner スクリプトに依存するような書き方で開発しているのなら,これらのスクリプトは Rails にはもはや含まれないことを知る必要がある.必要であればirs_process_scriptsプラグインを使おう.
- render_component は Rails 2.3 では "廃止予定" から "存在しない" になった.もし必要なら,render_componentプラグインをインストールしてほしい.
- Rails コンポーネントのサポートはなくなった.
- もし統合テストでパフォーマンスを見るために script/performance/request を使っていたのなら,このスクリプトが Rails からなくなったことを知る必要がある.新しい request_profiler プラグインをインストールすれば,全く同じ機能を取り戻すことができる.
- セッションが遅延ロードされることになったので,ActionController::Base#session_enabled? は廃止予定になった.
- protect_from_forgery の :digest/:cecret オプションは廃止予定となり,効果がなくなる.
- いくつかの統合テストヘルパーが削除された.response.headers["Status"] と headers["Status"] はもはや何も返さなくなった.しかし status と status_message ヘルパーはまだ使える.response.headers["cookie"] と headers["cookie"] はもはやどんな CGI Cookie も返さなくなった.headers["Set-Cookie"] を調べて生の Cookie 情報を取得するか,クライアントに送信する Cookie の Hash を取得する Cookie ヘルパーを使うことができる.
- formatted_polymorphic_url が廃止予定となった.代わりに polymorphic_url を :format オプション付きで使おう.
クレジット
リリースノートは Mike Gunderloy によってコンパイルされた.