Hatena::ブログ(Diary)

なんとなく日記 このページをアンテナに追加 RSSフィード

2009-02-10

[][]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 に関わる変更点をまとめておく.

ActionController::Base.session_store = :active_record_store

に変更することもまだできる.

ActionController::Base.session = { :key => "..." }

の形式のまま.

config.action_controller.session = {:session_key => foo}

ではなく

config.action_controller.session = {:key => foo}

を使うようになる.

Rails エンジンへの一新されたサポート

バージョンアップ後,Rails 2.3 は Rails エンジン*1の新しい特徴を提供する.第一に,routes.rb のようなルーティングファイルは自動的に読み込み・再読み込みされる(他のプラグインのルーティングファイルでも同様).第二に,もしプラグインに app フォルダーがあれば,その app/[models|controllers|helpers] は自動的に Rails のロードパスに追加される.エンジンは view のパスの追加もサポートする.

ドキュメント

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 でソートした結果が得られる(もちろん上書きすればそうではないが)

コールバックの多重条件

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

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 を使うようになったことだ.

respond_to の最適化

Rails-Merb チームの合流による最初の果実は,Rails 2.3 が respond_to の最適化を含んでいることだろう.それはもちろんリクエストの MIME 型に応じて結果を整形することができる,多くの Rails アプリケーションで使われている.method_missing の呼び出しを削除,プロファイリングと微調整により,3種類のフォーマットを切り替える respond_to への単純な呼び出しのパフォーマンスが 8% 向上した.いいところは?アプリ側のコードを書き換えること無く,高速化できることだ.

キャッシュパフォーマンスの改善

Rails 2.3 ではリクエストごとのローカルキャッシュを保存するようになった.不必要な読み込みを抑え,サイトのパフォーマンスを向上させる.当初は MemCacheStore に限定されていたが,必要なメソッドが実装されているあらゆる保存先を選べるようになった.

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 をレンダリングするようになる.ローカライズされたテンプレートが無い場合は,デフォルトのものが使われる.RailsI18n#available_locales と I18n::SimpleBackend#available_locales が追加され,有効な locale の Array が帰ってくる.

その他の Action Controller の変更
  • ETag 処理を少しだけ整理した.Rails 2.3 は response body が無いか send_file でファイルを送信するときには,ETag ヘッダーをスキップするようになった.
  • 携帯サイトのプロキシーは一般的に正しく設定されていないので,RailsIP 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'})
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 が返る.

Object#tap のバックポート

Object#tap は Ruby 1.9Ruby 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"
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

これは既存のコードの上にテンプレートの変更を重ねることになる.

静かなバックトレース

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/JRubyRails のすべてが一緒にロードされることが求められる.

他の Railties の変更

廃止予定

古いコードのいくつかがこのリリースで廃止予定となる.

クレジット

リリースノートは Mike Gunderloy によってコンパイルされた.

*1:他のアプリケーションに埋め込み可能な Rails アプリRails アプリ

*2:要するにインターフェイスは変わっていないってこと

*3:例えば SSL と非 SSL のホストを自動的に切り替えられるとか,分散に使えそう?

*4:Well, now it's baked right into Rails.

*5:This feature also enables prettier printing from any gem in the backtrace.

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証