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.checkbox :_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. このエントリーをはてなブックマークに追加