Ruby on Rails 2.3 リリースノート

Rails 2.3では、Rackの広範な統合、Railsエンジンのサポートの刷新、Active Recordのネストされたトランザクション、ダイナミックスコープとデフォルトスコープ、統一レンダリング、より効率のよいルーティング、アプリケーションテンプレート、静かなバックトレースといったさまざまな新機能や改善機能が提供されています。このリストは主要なアップグレードをカバーしていますが、すべての小さなバグフィックスや変更を含んでいるわけではありません。すべてを見たい場合は、GitHubのメインRailsリポジトリのコミットリスト をチェックするか、個別のRailsコンポーネントの CHANGELOG ファイルを確認してください。

目次

  1. アプリケーションアーキテクチャ
  2. ドキュメント
  3. Ruby 1.9.1 のサポート
  4. Active Record
  5. Action Controller
  6. Action View
  7. Active Support
  8. Railties
  9. 非推奨化されたもの
  10. クレジット表記

1 アプリケーションアーキテクチャ

Railsアプリケーションのアーキテクチャには、モジュール式WebサーバインターフェースであるRackの完全統合と、Railsエンジンの新たなサポートという2つの大きな変更があります。

1.1 Rackの統合

Railsは、これまでのCGIと決別し、あらゆる場所でRackを使うようになりました。このため、非常に多くの内部変更が必要となり、その結果、Railsはプロキシインタフェースを通じてCGIをサポートするようになりました(ただし、CGIを使っている人も心配ありません)。それでも、これはRails内部に対する大きな変更です。2.3にアップグレードしたら、ローカル環境と本番環境でテストする必要があります。以下などについてテストが必要です。

  • セッション
  • Cookie
  • ファイルアップロード
  • JSON/XML API

以下はRack関連の変更点の概要です。

  • script/server は rackup 設定ファイルが存在すれば、それを取得します。これは Rack と互換性のある全てのサーバをサポートすることを意味します。デフォルトでは config.ru ファイルを探索しますが、-c スイッチでこれを上書きできます。
  • FCGIハンドラはRackを経由します。
  • ActionController::Dispatcher は独自のデフォルトミドルウェアスタックを保持しています。ミドルウェアは注入・並べ替え・削除できます。ミドルウェアスタックは起動時にチェーンにコンパイルされます。ミドルウェアスタックは environment.rb で設定できます。
  • ミドルウェアスタックを調べられるrake middlewareタスクが追加されました。これはミドルウェアスタックの読み込み順序をデバッグするのに便利です。
  • 結合テストのランナーが、ミドルウェアとアプリケーションのスタック全体を実行するように変更されました。これにより、結合テストは Rack ミドルウェアのテストに最適になりました。
  • ActionController::CGIHandler は Rack の後方互換性のある CGI ラッパーです。CGIHandler は古い CGI オブジェクトを受け取り、その環境情報を Rack と互換性のある形に変換します。
  • CgiRequestCgiResponse は削除されました。
  • セッションストアがlazy loading(遅延読み込み)されるようになりました。リクエスト中に一度もセッションオブジェクトにアクセスしなかった場合、セッションデータを読み込むことはなくなりました(cookieの解析、memcacheからのデータ読み込み、Active Recordオブジェクトの探索)。
  • クッキーの値を設定するテストで CGI::Cookie.new が不要になりました。request.cookies["foo"]String値を代入すれば期待どおりcookieが設定されます。
  • CGI::Session::CookieStoreActionController::Session::CookieStore に置き換えられました。
  • CGI::Session::MemCacheStoreActionController::Session::MemCacheStore に置き換えられました。
  • CGI::Session::ActiveRecordStoreActiveRecord::SessionStore に置き換えられました。
  • セッションストアは引き続き ActionController::Base.session_store = :active_record_store で変更できます。
  • デフォルトのセッションオプションは引き続き ActionController::Base.session = { :key => "..." } で設定できます。ただし :session_domain オプション名は :domain に変更されました。
  • 従来リクエスト全体をラップしていたミューテックスは、 ActionController::Lock ミドルウェアに移動しました。
  • ActionController::AbstractRequestActionController::Request は統合されました。新しい ActionController::RequestRack::Request を継承しています。これは、テストリクエストにおける response.headers['type'] へのアクセスに影響します。代わりに response.content_type をお使いください。
  • ActiveRecord::QueryCache ミドルウェアは、 ActiveRecord がロードされると自動的にミドルウェアスタックに挿入されます。このミドルウェアは、リクエストごとの Active Record クエリキャッシュのセットアップやクリアを行います。
  • RailsのルータとコントローラのクラスはRackの仕様に準拠するようになりました。コントローラを直接呼び出すには、 SomeController.call(env) を使います。ルータはルーティングパラメータを rack.routing_args に保存します。
  • ActionController::RequestRack::Request を継承するようになりました。
  • config.action_controller.session = { :session_key => 'foo', ... の代わりに、 config.action_controller.session = { :key => 'foo', ... をお使い下さい。
  • ミドルウェア ParamsParser を使うと、XML、JSON、または YAML リクエストを前処理して、任意の Rack::Request オブジェクトで正常に読み込めるようになりました。

1.2 Railsエンジンを新たにサポート

ここしばらくアップグレードがありませんでしたが、Rails 2.3ではRailsエンジン(他のアプリケーションに組み込めるRailsアプリケーション)にいくつかの新機能が追加されました。まず、エンジン内のルーティングファイルは routes.rb ファイルと同様に自動的にロード・リロードされるようになりました(これは他のプラグイン内のルーティングファイルについても同様です)。次に、プラグインにappフォルダがある場合、app/[models|controllers|helpers]は自動的にRailsの読み込みパスに追加されます。エンジンもビューパスの追加をサポートするようになり、Action MailerやAction Viewはエンジンや他のプラグインからのビューを利用するようになりました。

2 ドキュメント

RailsガイドプロジェクトはRails 2.3向けにガイドをいくつも追加しました。さらに、edgeguides.rubyonrails.orgという別サイトでRails Edgeガイド(英語のみ)を参照できるようになりました。また、ドキュメント関連ではRails wikiやRails Bookの再立ち上げなども行われました(訳注: Rails wikiとRails Bookは現在は動いていません)。

3 Ruby 1.9.1 のサポート

Rails 2.3は、Ruby 1.8および現在リリースされているRuby 1.9.1のどちらでも、独自のテストにすべてパスするはずです。ただし1.9.1への移行には、Railsコアだけでなく、データアダプタ、プラグイン、その他依存するコードのすべてをRuby 1.9.1互換性でチェックする必要があることにご注意下さい。

4 Active Record

Rails 2.3のActive Recordでは、非常に多くの新機能追加とバグフィックスが施されています。特に、ネステッド属性、ネステッドトランザクション、動的スコープとデフォルトスコープ、およびバッチ処理がハイライトです。

4.1 ネステッド属性

Active Recordは、モデルのネステッド属性を以下のように直接更新できるようになりました。

class Book < ActiveRecord::Base
  has_one :author
  has_many :pages

  accepts_nested_attributes_for :author, :pages
end

ネステッド属性を有効にすると、レコードと関連する子レコードを自動的に(かつアトミックに)保存し、子を意識したバリデーションを行い、ネステッドフォームをサポートします(後述)。

また、:reject_if オプションを使うことで、ネステッド属性によって追加される新しいレコードに対する要件を指定することもできます。

accepts_nested_attributes_for :author,
  :reject_if => proc { |attributes| attributes['name'].blank? }

4.2 ネステッドトランザクション

要望の多かったネステッドトランザクションが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)  # => Adminだけを返す

ネステッドトランザクションでは、外側のトランザクションの状態に影響を与えずに内側のトランザクションをロールバックできます。トランザクションをネストしたい場合は、明示的に :requires_new オプションを追加する必要があります。そうしないと、ネステッドトランザクションは単に親トランザクションの一部になります(現在のRails 2.2ではそうなっています)。ネステッドトランザクションは内部で セーブポイントを使う ので、真のネステッドトランザクションを持たないデータベースでもサポートされます。また、テスト中にこれらのトランザクションをトランザクションフィクスチャでうまく動作させるために、ちょっとしたマジックも使っています。

4.3 動的スコープ

Railsのダイナミックファインダーメソッド(find_by_color_and_flavorのような動的に生成されるメソッド)や名前付きスコープ(再利用可能なクエリ条件をcurrently_activeのようにフレンドリーな名前にカプセル化できる)は既にご存知でしょう。これらに加えて動的なスコープメソッドも使えるようになりました。このアイデアは、以下のように動的なフィルタリングやメソッドチェインを可能にする構文をまとめることです。

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

動的スコープは、何も定義せずにすぐ使えます。

4.4 デフォルトスコープ

Rails 2.3では、名前付きスコープに似たデフォルトスコープという概念が導入されます。これはモデル内のすべての名前付きスコープやfindメソッドに適用されます。たとえば、default_scope :order => 'name ASC'と書けば、そのモデルからレコードを取得するときはいつでも名前順でソートされて出力されます(もちろん、このオプションをオーバーライドしない限り)。

4.5 バッチ処理

find_in_batches を使うことで、メモリに負担をかけずにActive Record モデルの大量のレコードを処理できるようになりました。

Customer.find_in_batches(:conditions => {:active => true}) do |customer_group|
  customer_group.each { |customer| customer.update_account_balance! }
end

find_in_batches には、ほとんどの find オプションを渡せます。ただし、返すレコードの順序を指定することや (常に主キーの昇順で返される整数値でなければなりません)、 :limit オプションを使うことはできません。代わりに、 :batch_size オプション (デフォルトは 1000件) を使用して、各バッチで返されるレコードの数を設定できます。

新しい find_each メソッドは、個々のレコードを返す find_in_batches のラッパーで、検索自体はバッチ処理で行われます (デフォルトでは 1000 件) 。

Customer.find_each do |customer|
  customer.update_account_balance!
end

この方法はバッチ処理でのみ使うようご注意ください。少数のレコード(1000件以下)の場合は、通常のfindメソッドをループで回してください。

4.6 コールバックで複数条件を指定

Active Record コールバックを使うときに、同じコールバックで :if:unless オプションを組み合わせ、複数の条件を配列として指定できるようになりました。

before_save :update_credit_rating, :if => :active,
  :unless => [:admin, :cash_only]
  • リードコントリビュータ: L. Caviola ### havingで検索

:having オプション(および has_manyhas_and_belongs_to_many 関連付け)が追加され、グループ化された検索結果のレコードを検索でフィルタできるようにました。SQL の知識が豊富な人ならご存知のように、グループ化された結果に基づいてフィルタをかけられるようになります。

developers = Developer.find(:all, :group => "salary",
  :having => "sum(salary) > 10000", :select => "salary")

4.7 MySQLコネクションの再接続

MySQLコネクションで再接続フラグをサポートされました。trueに設定すると、コネクションが切れてあきらめる前にクライアントがサーバーへの再接続を試みます。Railsアプリケーションでこの動作を有効にするために、database.ymlでMySQL接続に reconnect = true を設定できるようになりました。デフォルトは false なので、既存のアプリケーションの動作は変わりません。

4.8 その他のActive Recordの変更点

  • has_and_belongs_to_many プリロードの生成 SQL から余分な AS が削除され、いくつかのデータベースの動作が改善されました。
  • ActiveRecord::Base#new_record? は、既存のレコードが存在する場合に nil ではなく false を返すようになりました。
  • has_many :through の関連付けにおいて、テーブル名の引用符のバグが修正されました。
  • updated_at タイムスタンプに特定のタイムスタンプを指定できるようになりました: cust = Customer.create(:name => "ABC Industries", :updated_at => 1.day.ago).
  • find_by_attribute! 呼び出しに失敗した場合のエラーメッセージを改善しました。
  • Active Record の to_xml サポートに :camelize オプションが追加され、柔軟性が少し高まりました。
  • before_updatebefore_create のコールバックをキャンセルする際のバグが修正されました。
  • JDBC 経由でデータベースをテストするための Rake タスクが追加されました。
  • validates_length_of は、 :in または :within オプション (オプションが指定された場合) でカスタムエラーメッセージを使うようになりました。
  • スコープ付き select のカウントが正しく動作するようになり、 Account.scoped(:select => "DISTINCT credit_limit").count のようなことができるようになりました。
  • ActiveRecord::Base#invalid?ActiveRecord::Base#valid? の逆として動作するようになりました。

5 Action Controller

Action Controllerは、今回のリリースでレンダリングに関する大幅な変更と、ルーティングなどの改善を行いました。

5.1 レンダリング方法の統一

ActionController::Base#render でレンダリング対象を指定する方法がよりスマートになりました。レンダリング対象を指定するだけで、正しい結果が期待できます。以前のバージョンのRailsでは、以下のようにレンダリングで明示的な情報を提供する必要が生じることがよくありました。

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は、レンダリング対象の冒頭にスラッシュがある場合、スラッシュが途中にある場合、スラッシュがまったくない場合に応じて、ファイル、テンプレート、アクションのいずれかを選択します。アクションをレンダリングするときに、文字列の代わりにシンボルも使えます。その他のレンダリングスタイル (:inline, :text, :update, :nothing, :json, :xml, :js) では、引き続き明示的なオプションが必要です。

5.2 Application Controllerがリネームされた

application.rbで特殊なケースのネーミングにいつも悩まされている方へ朗報です。Rails 2.3ではapplication_controller.rbという名前に代わりました。さらに、新しい rake タスク rake rails:update:application_controller が用意され、これを自動的に実行できます(これは通常の rake rails:update プロセスの一部として実行されます)。

5.3 HTTPダイジェスト認証のサポート

Railsでは、HTTPダイジェスト認証がビルトインでサポートされるようになりました。これを使うには、以下のようにユーザーのパスワードを返すブロックを付けて authenticate_or_request_with_http_digest を呼び出します(パスワードはハッシュ化され、送信されたcredentialと比較されます)。

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

5.4 ルーティングの効率向上

Rails 2.3では、ルーティングにいくつかの重要な変更が加えられています。formatted_ ルーティングヘルパーがなくなり、代わりに :format をオプションとして渡せるようになりました。これにより、どのリソースに対してもルート生成プロセスが50%削減され、かなりの量のメモリが節約できます(大規模なアプリケーションでは最大100MB)。自分のコードが formatted_ ヘルパーを使っていたとしても、当面は動作しますが、この動作は非推奨であり、新しい標準でルーティングを書き直せば、アプリケーションの効率は向上します。もう一つの大きな変更点は、Railsが routes.rb だけでなく、複数のルーティングファイルをサポートするようになったことです。RouteSet#add_configuration_file を使えば、現在読み込まれているルーティングをクリアすることなく、いつでも新しいルートを取り込めます。この変更はRailsエンジンで最も有用ですが、ルーティングをバッチで一括読み込みする必要がある任意のアプリケーションで利用できます。

5.5 Rackベースの遅延読み込みセッション

大きな変更点として、Action Controller のセッションストレージの基盤が Rack レベルに押し下げられたことが挙げられます。Railsアプリケーションからはまったく見えないはずですが、コードにはかなりの作業が含まれています(ボーナスとして、古いCGIセッションハンドラ周辺の厄介なパッチがいくつか削除されました)。Rails以外のRackアプリケーションもRailsアプリケーションと同じセッションストレージハンドラにアクセスできる (つまり同じセッションにアクセスできる) からです。さらに、セッションは遅延読み込みされるようになりました(フレームワークの他の部分の読み込み改善と同様)。つまり、セッションが不要な場合に明示的に無効にする必要はなくなりました。セッションを参照しないようにすれば、セッションは読み込まれません。

5.6 MIMEタイプの扱いが変更

RailsでMIMEタイプを処理するコードには、いくつかの変更があります。まず、 MIME::Type=~ 演算子を実装し、同義語を持つタイプの存在をチェックする必要がある場合の記法がずっと明確になりました。

if content_type && Mime::JS =~ content_type
  # 何かする
end

Mime::JS =~ "text/javascript"        => true
Mime::JS =~ "application/javascript" => true

もう1つの変更は、フレームワークがさまざまな場所でJavaScriptをチェックするときに Mime::JS を使うようになり、それらの代替をきれいに処理できるようになったことです。

5.7 respond_toの最適化

RailsとMerbチームの合併による最初の成果として、Rails 2.3にはrespond_toメソッドの最適化が含まれています。このメソッドはもちろん多くのRailsアプリケーションで多用されていて、送られてきたリクエストのMIMEタイプに応じてコントローラが異なる結果をフォーマットできるようになっています。method_missingの呼び出しをなくし、プロファイリングと微調整を行った結果、3つのフォーマットを切り替えるシンプルな respond_to で、1秒あたりのリクエスト数が8%向上しています。最も優れている点は、このスピードアップを利用するためにアプリケーションのコードを変更する必要がまったくないことです。

5.8 キャッシュのパフォーマンス向上

Railsは、リモートキャッシュストアから読み込んだデータをリクエストごとにローカルキャッシュとして保持するようになり、不要な読み込みを減らしてサイトのパフォーマンスを向上させました。この機能はもともと MemCacheStore に限定されていましたが、必要なメソッドを実装しているリモートストアであれば、どのストアでも利用できます。

5.9 ビューのローカライズ

Railsは、設定したロケールに応じてローカライズされたビューを提供できるようになりました。たとえば、 Posts コントローラに show アクションがあると、デフォルトではapp/views/posts/show.html.erb がレンダリングされます。しかしI18n.locale = :da と設定すると、 app/views/posts/show.da.html.erb がレンダリングされるようになります。ローカライズされたテンプレートが存在しない場合は、装飾なしバージョンが使われます。Railsには I18n#available_localesI18n::SimpleBackend#available_locales もあり、これらは現在のRailsプロジェクトで利用可能な翻訳の配列を返します。

さらに、同じ方法でpublicディレクトリにあるrescueファイルもローカライズできます。たとえば、 public/500.da.htmlpublic/404.en.html が使えるようになります。

5.10 翻訳APIをパーシャルでスコープ化

翻訳APIの変更により、パーシャル内のキー翻訳を簡単に書けるようになり、記述の重複が少なくなりました。people/index.html.erb テンプレートから translate(".foo") を呼び出すと、実際には I18n.translate("people.index.foo") を呼び出します。キーの前にピリオドがない場合は、以前と同じようにAPIはスコープなしとなります。

5.11 その他のAction Controllerの変更

  • ETag の取り扱いが少し改善されました。レスポンスにbodyがないとき、または send_file でファイルを送信するときに、Rails は ETag ヘッダの送信をスキップするようになりました。
  • RailsによるIPスプーフィングのチェックは、携帯電話のトラフィックが多いサイトで邪魔になることがありますが。そのような場合はActionController::Base.ip_spoofing_check = false と設定することで、チェックを完全に無効にできるようになりました。
  • ActionController::Dispatcher は独自のミドルウェアスタックを実装しており、 rake middleware を実行することで確認できます。
  • cookieセッションが永続的なセッション識別子を持つようになりました。これはサーバーサイドストアとの API 互換性があります。
  • send_filesend_data:type オプションで、send_file("fabulous.png", :type => :png)のようにシンボルを使えるようになりました。
  • map.resources:only:except オプションは、ネストしたリソースには継承されなくなりました。
  • バンドルされている memcached クライアントがバージョン 1.6.4.99 に更新されました。
  • プロキシキャッシュで動作するように expires_instale?fresh_when メソッドに :public オプションを指定できるようになりました。
  • RESTful なmemberルーティングが追加され、 :requirements オプションが正しく動作するようになりました。
  • 浅いルーティングで、名前空間が適切に考慮されるようになりました。
  • polymorphic_url が、不規則に活用される複数形の名前を持つオブジェクトをより適切に扱えるようになりました。

6 Action View

Rails 2.3のAction Viewでは、ネステッドモデルのフォーム、renderの改善、日付選択ヘルパーのより柔軟な表示、アセットキャッシングの高速化などが行われました。

6.1 ネステッドオブジェクトのフォーム

親モデルが子オブジェクトのネステッド属性を受け入れる場合(上述のActive Recordのセクションの説明を参照)、 form_forfield_for を使ってネステッドフォームを作成できます。これらのフォームは任意の深さにネスト可能で、少ないコードで複雑なオブジェクト階層を単一のビューで編集できます。たとえば以下のようなモデルがあるとします。

class Customer < ActiveRecord::Base
  has_many :orders

  accepts_nested_attributes_for :orders, :allow_destroy => true
end

Rails 2.3では以下のようにビューを書けます。

<% 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 %>

6.2 パーシャルのレンダリングがスマートに

render メソッドは年々賢くなり、今はさらに賢くなりました。オブジェクトやコレクションと適切なパーシャルがあり、命名が一致する場合は、オブジェクトをrenderするだけで動くようになりました。たとえばRails 2.3では、以下のrenderコールがビューで使えます(命名が適切であると仮定します)。

# これは以下と同様
# render :partial => 'articles/_article', :object => @article
render @article

# これは以下と同様
# render :partial => 'articles/_article', :collection => @articles
render @articles

6.3 日付セレクタヘルパーのプロンプト表示

Rails 2.3では、様々な日付選択ヘルパー(date_selecttime_selectdatetime_select)で、コレクション選択ヘルパーと同様にカスタムプロンプトを指定できます。プロンプトには、文字列の他に、様々なコンポーネントのプロンプト文字列のハッシュを渡せます。また、 :prompttrue に設定することで、一般的なプロンプトも利用できます。

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'})

6.4 AssetTagのタイムスタンプキャッシュ

静的アセットパスに「キャッシュバスター」としてタイムスタンプを追加するRailsの慣習はよく知られていると思います。これは、画像やスタイルシートなどの古いコピーが、サーバーで変更されたときにユーザーのブラウザのキャッシュから提供されないようにするためのものです。Action Viewの設定オプション cache_asset_timestamps で、この動作を変更できるようになりました。キャッシュを有効にすると、Railsは最初にアセットを提供するときにタイムスタンプを一度算出して値を保存します。これは、静的アセットを提供するための(コストのかかる)ファイルシステム呼び出しが減ることを意味しますが、その代わり、サーバーの実行中にアセットを変更しても変更がクライアントに反映されることも期待できなくなります。

6.5 アセットホストをオブジェクトとして宣言

エッジRailsでは、アセットホストを「呼び出しに応答する特定のオブジェクト」として宣言できるようになり、アセットホストの柔軟性が高まりました。これにより、アセットホストで必要などんな複雑なロジックも実装できるようになります。

6.6 grouped_options_for_selectヘルパーメソッド

アクションビューには、セレクタボックスの生成を支援するヘルパーがすでにたくさんありますが、もうひとつ増えました。grouped_options_for_select です。これは以下のように、文字列の配列またはハッシュを受け取って、 option タグを optgroup タグでラップした文字列に変換するものです。

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>

6.7 フォームのセレクタヘルパーを無効にするオプションタグ

フォームのセレクタヘルパー(selectoptions_for_select など)が:disabled オプションをサポートするようになり、結果のタグで無効にしたい単一の値または値の配列を受け取れるようになりました。

select(:post, :category, Post::CATEGORIES, :disabled => 'private')

上は以下を返します。

<select name="post[category]">
<option>story</option>
<option>joke</option>
<option>poem</option>
<option disabled="disabled">private</option>
</select>

また、無名関数を使えば、コレクションからどのオプションを選択または無効にするかを実行時に決定することもできます。

options_from_collection_for_select(@product.sizes, :name, :id, :disabled => lambda{|size| size.out_of_stock?})

6.8 テンプレート読み込みに関する注意

Rails 2.3では、キャッシュされたテンプレートを特定の環境で有効または無効にする機能があります。キャッシュされたテンプレートは、レンダリング時に新しいテンプレートファイルがあるかどうかをチェックしないので、速度が向上します。しかし、これは同時に、サーバを再起動せずに「その場で」テンプレートを置き換えられないということでもあります。

ほとんどの場合、production環境ではテンプレートのキャッシュを有効にしたいと思うでしょう。これは production.rb ファイルで設定します。

config.action_view.cache_template_loading = true

上の設定は、新しいRails 2.3アプリケーションではデフォルトで生成されます。古いバージョンのRailsからアップグレードした場合、Railsはproduction環境とtest環境ではテンプレートをキャッシュするようにデフォルトで設定しますが、development環境では設定しません。

6.9 その他のAction Viewの変更

  • CSRF 保護トークンの生成がシンプルになりました。Rails はセッション ID をいじくりまわすのではなく、 ActiveSupport::SecureRandom によって生成されたシンプルなランダム文字列を使うようになりました。
  • auto_link が、生成されたメールのリンクにオプション(:target:class など)を適切に適用するようになりました。
  • autolink ヘルパーがリファクタリングされ、より直感的に使えるようになりました。
  • URL に複数のクエリパラメータがある場合でも、 current_page? が正しく動作するようになりました。

7 Active Support

Active Supportでも、Object#tryなどいくつかの興味深い変更が行われました。

7.1 Object#try

多くの人が、オブジェクトに対する操作を試みるときにtry()を使うというアイデアを採用しています。特にビューでは、<%= @person.try(:name) %>のようなコードを書くことでnilチェックを回避できるので便利です。この機能がRailsに組み込まれました。Railsに実装されたこの機能は、privateメソッドに対して NoMethodError を発生し、オブジェクトがnilの場合は常に nil を返します。

7.2 Object#tapのバックポート

Object#tapRuby 1.9 および 1.8.7 に追加されたもので、Rails に以前からある returning メソッドに似ています。ブロックをyieldして、yieldしたオブジェクトを返すというものです。Railsは現在、これを古いバージョンのRubyでも使えるようにするコードを含んでいます。

7.3 XMLminiのパーサーが差し替え可能に

Active SupportのXML解析サポートで、パーサーを別のものに差し替えられるようになり、柔軟性が増しました。デフォルトでは、標準的なREXMLの実装を使用しますが、適切なgemがインストールされていれば、高速なLibXMLやNokogiriの実装を自分のアプリケーションに簡単に指定できます。

XmlMini.backend = 'LibXML'

7.4 TimeWithZoneで秒以下をサポート

Time クラスと TimeWithZone クラスに、時刻を XML フレンドリーな文字列で返す xmlschema メソッドが含まれました。Rails 2.3 のTimeWithZoneTime と同じ引数になり、返される文字列の小数第2位の桁数を指定できるようになりました。

Time.zone.now.xmlschema(6) # => "2009-01-16T13:00:06.13653Z"

7.5 JSONキーの引用符

json.orgサイトで仕様を調べると、JSON構造体のキーはすべて文字列でなければならず、二重引用符で囲まなければならないことがわかります。Rails 2.3からは、数値キーについても適切に扱うようになりました。

7.6 その他のActive Supportの変更

  • Enumerable#none?で、与えられたブロックにマッチする要素がないことをチェックできます。
  • Active Support delegatesを使う場合、新しい :allow_nil オプションで、ターゲットオブジェクトが nil のときに例外を発生させずにnil を返すようになりました。
  • ActiveSupport::OrderedHasheach_keyeach_value を実装しました。
  • ActiveSupport::MessageEncryptor は(cookieのような)信頼できない場所に保存する情報を暗号化する簡単な方法を提供します。
  • Active Support の from_xml がXmlSimple に依存しなくなりました。その代わりに、Railsは必要な機能だけを備えた、独自のXmlMini実装を含むようになりました。これにより、RailsはこれまでバンドルされていたXmlSimpleのコピーから解放されました。
  • privateメソッドをメモ化すると、その結果もprivateになります。
  • String#parameterize にオプションの区切り文字を渡せるようになりました。例: "Quick Brown Fox".parameterize('_') => "quick_brown_fox".
  • number_to_phone に7桁の電話番号を渡せるようになりました。
  • ActiveSupport::Json.decodeu0000 形式のエスケープシーケンスを処理するようになりました。

8 Railties

上記のRackの変更に加え、Railties(Railsのコアコード)には、Rails Metal、アプリケーションテンプレート、Quiet Backtraceなど、多くの重要な変更が加えられています。

8.1 Rails Metal

Rails Metalは、Railsアプリケーションの内部に超高速なエンドポイントを提供する新しいメカニズムです。MetalクラスはルーティングとAction Controllerをバイパスして、素の速度を提供します(もちろん、Action Controllerにあるすべてのものが使えなくなりますが)。これは、Railsを「ミドルウェアスタックを公開したRackアプリケーション」にするための最近の基礎作業の上に構築されています。Metalエンドポイントはアプリケーションやプラグインから読み込めます。

8.2 アプリケーションテンプレート

Rails 2.3には、Jeremy McAnallyによるrgアプリケーションジェネレータが組み込まれています。つまり、Railsにテンプレートベースのアプリケーション生成機能が組み込まれたということです。(他の多くのユースケースの中から)すべてのアプリケーションに含めたいプラグインのセットがある場合、テンプレートを一度セットアップしておけば、railsコマンドを実行するときにそれらが常に適用されるようになります。また、既存のアプリケーションにテンプレートを適用するrakeタスクも用意されています。

$ rake rails:template LOCATION=~/template.rb

上を実行すると、プロジェクトにすでに含まれているコードの上に、テンプレートによる変更を配置します。

8.3 Quieter Backtrace

thoughtbotの Quiet Backtrace プラグインはTest::Unit のバックトレースから選択的に行を削除できますが、Rails 2.3ではそれをベースにした ActiveSupport::BacktraceCleanerRails::BacktraceCleaner をコアに実装しています。これは、フィルタ(バックトレース行を正規表現で置換する)とサイレンサー(バックトレース行を完全に削除する)の両方をサポートします。Railsは新しいアプリケーションで最も一般的なノイズを取り除くためにサイレンサーを自動的に追加し、フィルタに追加するものを保存できるconfig/backtrace_silencers.rb ファイルを生成します。この機能により、バックトレース中の任意のgemの出力もpretty printされるようになります。

8.4 遅延読み込みと自動読み込みでdevelopmentモードの起動が高速化

Railsの一部(とその依存関係)が実際に必要なときだけメモリに読み込まれるようにするために、かなりの作業が行われました。コアフレームワークであるActive Support、Active Record、Action Controller、Action Mailer、Action Viewは、それぞれのクラスをautoloadで遅延読み込みするようになりました。この作業によりメモリフットプリントが抑えられ、Rails全体のパフォーマンスが向上するはずです。

また、起動時にコアライブラリを自動読み込みするかどうかを(新しい preload_frameworks オプションで)指定できます。デフォルトの false ではRailsが少しずつ自動読み込みされますが、一度にすべてを取り込む必要が生じることもあります(PassengerとJRubyは、Railsのすべてを一括で読み込むことを希望しています)。

8.5 rake gemタスクが書き直された

様々な rake gem タスクの内部が、多くのケースでうまく動くよう大幅に改訂されました。gem システムは開発時の依存関係と実行時の依存関係の違いを認識するようになり、unpackingがより堅牢になり、gem の状態問い合わせで返される情報が改善され、スクラッチでアプリを開発するときに依存関係で「卵が先かニワトリが先か」問題を起こしにくくなりました。また、JRubyでgemコマンドを使うときや、すでにベンダリングされているgemの外部コピーを持ち込もうとする依存関係についても修正されています。

8.6 その他のRailties変更

  • Rails ビルド用に CI サーバを更新する手順が更新され、拡張されました。
  • Railsの内部テストが Test::Unit::TestCase から ActiveSupport::TestCase に変更され、RailsコアのテストでMochaが必須になりました。
  • デフォルトの environment.rb ファイルが整理されました。
  • dbconsole スクリプトで数字のみのパスワードを設定してもクラッシュしなくなりました。
  • Rails.rootPathname オブジェクトを返すようになりました。つまり、 File.join を使っている 既存のコードをクリーンアップしてjoin メソッドを直接使えるようになりました。
  • CGIやFCGIのディスパッチを扱う/publicの様々なファイルが、デフォルトではすべてのRailsアプリケーションで生成されなくなりました(必要であれば、railsコマンドを実行するときに --with-dispatchers を追加すればまだ取得できますし、後から rake rails:update:generate_dispatchers で追加することも可能です)。
  • Railsガイドの記法がAsciiDocからTextileマークアップに変更されました。
  • scaffoldで生成されるビューやコントローラが少し整理されました。
  • script/server に、特定のパスからRailsアプリケーションをマウントする --path 引数を渡せるようになりました。
  • gemのrakeタスクは、設定済みの gem がない場合に環境の読み込みをスキップするようになりました。これは、gem が見つからないために rake gems:install が実行できないといった「卵が先かニワトリが先か」問題の多くを解決するはずです。
  • Gems は正確に一度だけunpackされるようになりました。これは、ファイルの読み取り専用パーミッションでパックされた gem (hoeなど) の問題を解決します。

9 非推奨化されたもの

今回のリリースで、いくつかの古いコードが非推奨化されました。

  • めったにいないはずですが、Railsアプリのデプロイをinspector、reaper、spawnerスクリプトに依存している場合は、これらのスクリプトがRailsのコアに含まれなくなったことを知っておく必要があります。必要なら、irs_process_scriptsプラグインでコピーを手に入れられるはずです。
  • Rails 2.3 で render_component が "deprecated" から "nonexistent" に変更されました。それでも必要な場合は、render_component pluginをインストールするとよいでしょう。
  • Railsコンポーネントのサポートは削除されました。
  • script/performance/request スクリプトは現在Railsのコアから削除されました。結合テストでこのスクリプトを用いてパフォーマンスをチェックしている方は、別の新しい方法を学ぶ必要があります。新しいrequest_profilerプラグインをインストールすれば、まったく同じ機能を復元できます。
  • ActionController::Base#session_enabled? は、セッションが遅延読み込みされるようになったため非推奨化されました。
  • protect_from_forgery:digest:secret オプションは非推奨化されました(無効なオプションです)。
  • いくつかの結合テストヘルパーが削除されました。response.headers["Status"]headers["Status"] は何も返さなくなりました。Rack は戻り値のヘッダに "Status" を使うことを許可していません。しかし、 status ヘルパーや status_message ヘルパーは利用可能です。response.headers["cookie"]headers["cookie"] は CGI cookieを一切返さなくなりました。生のcookieヘッダを見るために headers["Set-Cookie"] を検査したり、クライアントに送信されたcookieのハッシュを取得するために cookies ヘルパーを利用することは可能です。
  • formatted_polymorphic_url は非推奨化されました。代わりに polymorphic_url:format をお使いください。
  • ActionController::Response#set_cookie:http_only オプション名は :httponly に変更されました。
  • to_sentence:connector オプションと :skip_last_comma オプションは、 :words_connector, :two_words_connector, :last_word_connector オプションに置き換わりました。
  • file_field コントロールが空になっているマルチパートフォームを送信すると、以前は空文字列がコントローラに送信されていましたが、現在はnilを送信するようになりました。これは、Rack のマルチパートパーサーと Rails の古いパーサーとの違いに起因します。

10 クレジット表記

リリースノート編集担当:Mike Gunderloy。このRails 2.3リリースノートは、Rails 2.3 RC2を元に編集されています。

フィードバックについて

Railsガイドは GitHub の yasslab/railsguides.jp で管理・公開されております。本ガイドを読んで気になる文章や間違ったコードを見かけたら、気軽に Pull Request を出して頂けると嬉しいです。Pull Request の送り方については GitHub の README をご参照ください。

原著における間違いを見つけたら『Rails のドキュメントに貢献する』を参考にしながらぜひ Rails コミュニティに貢献してみてください 🛠💨✨

本ガイドの品質向上に向けて、皆さまのご協力が得られれば嬉しいです。

Railsガイド運営チーム (@RailsGuidesJP)

支援・協賛

Railsガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。

  1. Star
  2. このエントリーをはてなブックマークに追加