Rails 2.3では、Rackの広範な統合、Railsエンジンのサポートの刷新、Active Recordのネストされたトランザクション、ダイナミックスコープとデフォルトスコープ、統一レンダリング、より効率のよいルーティング、アプリケーションテンプレート、静かなバックトレースといったさまざまな新機能や改善機能が提供されています。このリストは主要なアップグレードをカバーしていますが、すべての小さなバグフィックスや変更を含んでいるわけではありません。すべてを見たい場合は、GitHubのメインRailsリポジトリのコミットリスト をチェックするか、個別のRailsコンポーネントの CHANGELOG ファイルを確認してください。
Railsアプリケーションのアーキテクチャには、モジュール式WebサーバインターフェースであるRackの完全統合と、Railsエンジンの新たなサポートという2つの大きな変更があります。
Railsは、これまでのCGIと決別し、あらゆる場所でRackを使うようになりました。このため、非常に多くの内部変更が必要となり、その結果、Railsはプロキシインタフェースを通じてCGIをサポートするようになりました(ただし、CGIを使っている人も心配ありません)。それでも、これはRails内部に対する大きな変更です。2.3にアップグレードしたら、ローカル環境と本番環境でテストする必要があります。以下などについてテストが必要です。
以下はRack関連の変更点の概要です。
script/server は rackup 設定ファイルが存在すれば、それを取得します。これは Rack と互換性のある全てのサーバをサポートすることを意味します。デフォルトでは config.ru ファイルを探索しますが、-c スイッチでこれを上書きできます。ActionController::Dispatcher は独自のデフォルトミドルウェアスタックを保持しています。ミドルウェアは注入・並べ替え・削除できます。ミドルウェアスタックは起動時にチェーンにコンパイルされます。ミドルウェアスタックは environment.rb で設定できます。rake middlewareタスクが追加されました。これはミドルウェアスタックの読み込み順序をデバッグするのに便利です。ActionController::CGIHandler は Rack の後方互換性のある CGI ラッパーです。CGIHandler は古い CGI オブジェクトを受け取り、その環境情報を Rack と互換性のある形に変換します。CgiRequest と CgiResponse は削除されました。CGI::Cookie.new が不要になりました。request.cookies["foo"]にString値を代入すれば期待どおりcookieが設定されます。CGI::Session::CookieStore が ActionController::Session::CookieStore に置き換えられました。CGI::Session::MemCacheStore が ActionController::Session::MemCacheStore に置き換えられました。CGI::Session::ActiveRecordStore が ActiveRecord::SessionStore に置き換えられました。ActionController::Base.session_store = :active_record_store で変更できます。ActionController::Base.session = { :key => "..." } で設定できます。ただし :session_domain オプション名は :domain に変更されました。ActionController::Lock ミドルウェアに移動しました。ActionController::AbstractRequest と ActionController::Request は統合されました。新しい ActionController::Request は Rack::Request を継承しています。これは、テストリクエストにおける response.headers['type'] へのアクセスに影響します。代わりに response.content_type をお使いください。ActiveRecord::QueryCache ミドルウェアは、 ActiveRecord がロードされると自動的にミドルウェアスタックに挿入されます。このミドルウェアは、リクエストごとの Active Record クエリキャッシュのセットアップやクリアを行います。SomeController.call(env) を使います。ルータはルーティングパラメータを rack.routing_args に保存します。ActionController::Request は Rack::Request を継承するようになりました。config.action_controller.session = { :session_key => 'foo', ... の代わりに、 config.action_controller.session = { :key => 'foo', ... をお使い下さい。ParamsParser を使うと、XML、JSON、または YAML リクエストを前処理して、任意の Rack::Request オブジェクトで正常に読み込めるようになりました。ここしばらくアップグレードがありませんでしたが、Rails 2.3ではRailsエンジン(他のアプリケーションに組み込めるRailsアプリケーション)にいくつかの新機能が追加されました。まず、エンジン内のルーティングファイルは routes.rb ファイルと同様に自動的にロード・リロードされるようになりました(これは他のプラグイン内のルーティングファイルについても同様です)。次に、プラグインにappフォルダがある場合、app/[models|controllers|helpers]は自動的にRailsの読み込みパスに追加されます。エンジンもビューパスの追加をサポートするようになり、Action MailerやAction Viewはエンジンや他のプラグインからのビューを利用するようになりました。
RailsガイドプロジェクトはRails 2.3向けにガイドをいくつも追加しました。さらに、edgeguides.rubyonrails.orgという別サイトでエッジRailsのガイド(英語のみ)を参照できるようになりました。また、ドキュメント関連ではRails wikiやRails Bookの再立ち上げなども行われました(訳注: Rails wikiとRails Bookは現在は動いていません)。
Rails 2.3は、Ruby 1.8および現在リリースされているRuby 1.9.1のどちらでも、独自のテストにすべてパスするはずです。ただし1.9.1への移行には、Railsコアだけでなく、データアダプタ、プラグイン、その他依存するコードのすべてをRuby 1.9.1互換性でチェックする必要があることにご注意下さい。
Rails 2.3のActive Recordでは、非常に多くの新機能追加とバグフィックスが施されています。特に、ネステッド属性、ネステッドトランザクション、動的スコープとデフォルトスコープ、およびバッチ処理がハイライトです。
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? }
要望の多かったネステッドトランザクションが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ではそうなっています)。ネステッドトランザクションは内部で セーブポイントを使う ので、真のネステッドトランザクションを持たないデータベースでもサポートされます。また、テスト中にこれらのトランザクションをトランザクションフィクスチャでうまく動作させるために、ちょっとしたマジックも使っています。
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")
動的スコープは、何も定義せずにすぐ使えます。
Rails 2.3では、名前付きスコープに似たデフォルトスコープという概念が導入されます。これはモデル内のすべての名前付きスコープやfindメソッドに適用されます。たとえば、default_scope :order => 'name ASC'と書けば、そのモデルからレコードを取得するときはいつでも名前順でソートされて出力されます(もちろん、このオプションをオーバーライドしない限り)。
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メソッドをループで回してください。
each と呼ばれていました)。
Active Record コールバックを使うときに、同じコールバックで :if と :unless オプションを組み合わせ、複数の条件を配列として指定できるようになりました。
before_save :update_credit_rating, :if => :active, :unless => [:admin, :cash_only]
havingで検索:having オプション(および has_many と has_and_belongs_to_many 関連付け)が追加され、グループ化された検索結果のレコードを検索でフィルタできるようにました。SQL の知識が豊富な人ならご存知のように、グループ化された結果に基づいてフィルタをかけられるようになります。
developers = Developer.find(:all, :group => "salary", :having => "sum(salary) > 10000", :select => "salary")
MySQLコネクションで再接続フラグをサポートされました。trueに設定すると、コネクションが切れてあきらめる前にクライアントがサーバーへの再接続を試みます。Railsアプリケーションでこの動作を有効にするために、database.ymlでMySQL接続に reconnect = true を設定できるようになりました。デフォルトは false なので、既存のアプリケーションの動作は変わりません。
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! 呼び出しに失敗した場合のエラーメッセージを改善しました。to_xml サポートに :camelize オプションが追加され、柔軟性が少し高まりました。before_update や before_create のコールバックをキャンセルする際のバグが修正されました。validates_length_of は、 :in または :within オプション (オプションが指定された場合) でカスタムエラーメッセージを使うようになりました。Account.scoped(:select => "DISTINCT credit_limit").count のようなことができるようになりました。ActiveRecord::Base#invalid? が ActiveRecord::Base#valid? の逆として動作するようになりました。Action Controllerは、今回のリリースでレンダリングに関する大幅な変更と、ルーティングなどの改善を行いました。
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) では、引き続き明示的なオプションが必要です。
application.rbで特殊なケースのネーミングにいつも悩まされている方へ朗報です。Rails 2.3ではapplication_controller.rbという名前に代わりました。さらに、新しい rake タスク rake rails:update:application_controller が用意され、これを自動的に実行できます(これは通常の rake rails:update プロセスの一部として実行されます)。
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
Rails 2.3では、ルーティングにいくつかの重要な変更が加えられています。formatted_ ルーティングヘルパーがなくなり、代わりに :format をオプションとして渡せるようになりました。これにより、どのリソースに対してもルート生成プロセスが50%削減され、かなりの量のメモリが節約できます(大規模なアプリケーションでは最大100MB)。自分のコードが formatted_ ヘルパーを使っていたとしても、当面は動作しますが、この動作は非推奨であり、新しい標準でルーティングを書き直せば、アプリケーションの効率は向上します。もう一つの大きな変更点は、Railsが routes.rb だけでなく、複数のルーティングファイルをサポートするようになったことです。RouteSet#add_configuration_file を使えば、現在読み込まれているルーティングをクリアすることなく、いつでも新しいルートを取り込めます。この変更はRailsエンジンで最も有用ですが、ルーティングをバッチで一括読み込みする必要がある任意のアプリケーションで利用できます。
大きな変更点として、Action Controller のセッションストレージの基盤が Rack レベルに押し下げられたことが挙げられます。Railsアプリケーションからはまったく見えないはずですが、コードにはかなりの作業が含まれています(ボーナスとして、古いCGIセッションハンドラ周辺の厄介なパッチがいくつか削除されました)。Rails以外のRackアプリケーションもRailsアプリケーションと同じセッションストレージハンドラにアクセスできる (つまり同じセッションにアクセスできる) からです。さらに、セッションは遅延読み込みされるようになりました(フレームワークの他の部分の読み込み改善と同様)。つまり、セッションが不要な場合に明示的に無効にする必要はなくなりました。セッションを参照しないようにすれば、セッションは読み込まれません。
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 を使うようになり、それらの代替をきれいに処理できるようになったことです。
respond_toの最適化RailsとMerbチームの合併による最初の成果として、Rails 2.3にはrespond_toメソッドの最適化が含まれています。このメソッドはもちろん多くのRailsアプリケーションで多用されていて、送られてきたリクエストのMIMEタイプに応じてコントローラが異なる結果をフォーマットできるようになっています。method_missingの呼び出しをなくし、プロファイリングと微調整を行った結果、3つのフォーマットを切り替えるシンプルな respond_to で、1秒あたりのリクエスト数が8%向上しています。最も優れている点は、このスピードアップを利用するためにアプリケーションのコードを変更する必要がまったくないことです。
Railsは、リモートキャッシュストアから読み込んだデータをリクエストごとにローカルキャッシュとして保持するようになり、不要な読み込みを減らしてサイトのパフォーマンスを向上させました。この機能はもともと MemCacheStore に限定されていましたが、必要なメソッドを実装しているリモートストアであれば、どのストアでも利用できます。
Railsは、設定したロケールに応じてローカライズされたビューを提供できるようになりました。たとえば、 Posts コントローラに show アクションがあると、デフォルトではapp/views/posts/show.html.erb がレンダリングされます。しかしI18n.locale = :da と設定すると、 app/views/posts/show.da.html.erb がレンダリングされるようになります。ローカライズされたテンプレートが存在しない場合は、装飾なしバージョンが使われます。Railsには I18n#available_locales と I18n::SimpleBackend#available_locales もあり、これらは現在のRailsプロジェクトで利用可能な翻訳の配列を返します。
さらに、同じ方法でpublicディレクトリにあるrescueファイルもローカライズできます。たとえば、 public/500.da.html や public/404.en.html が使えるようになります。
翻訳APIの変更により、パーシャル内のキー翻訳を簡単に書けるようになり、記述の重複が少なくなりました。people/index.html.erb テンプレートから translate(".foo") を呼び出すと、実際には I18n.translate("people.index.foo") を呼び出します。キーの前にピリオドがない場合は、以前と同じようにAPIはスコープなしとなります。
send_file でファイルを送信するときに、Rails は ETag ヘッダの送信をスキップするようになりました。ActionController::Base.ip_spoofing_check = false と設定することで、チェックを完全に無効にできるようになりました。ActionController::Dispatcher は独自のミドルウェアスタックを実装しており、 rake middleware を実行することで確認できます。send_file と send_data の :type オプションで、send_file("fabulous.png", :type => :png)のようにシンボルを使えるようになりました。map.resources の :only と :except オプションは、ネストしたリソースには継承されなくなりました。expires_in、stale?、fresh_when メソッドに :public オプションを指定できるようになりました。:requirements オプションが正しく動作するようになりました。polymorphic_url が、不規則に活用される複数形の名前を持つオブジェクトをより適切に扱えるようになりました。Rails 2.3のAction Viewでは、ネステッドモデルのフォーム、renderの改善、日付選択ヘルパーのより柔軟な表示、アセットキャッシングの高速化などが行われました。
親モデルが子オブジェクトのネステッド属性を受け入れる場合(上述の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では以下のようにビューを書けます。
<% 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 %>
render メソッドは年々賢くなり、今はさらに賢くなりました。オブジェクトやコレクションと適切なパーシャルがあり、命名が一致する場合は、オブジェクトをrenderするだけで動くようになりました。たとえばRails 2.3では、以下のrenderコールがビューで使えます(命名が適切であると仮定します)。
# これは以下と同様 # render :partial => 'articles/_article', :object => @article render @article # これは以下と同様 # render :partial => 'articles/_article', :collection => @articles render @articles
Rails 2.3では、様々な日付選択ヘルパー(date_select、time_select、datetime_select)で、コレクション選択ヘルパーと同様にカスタムプロンプトを指定できます。プロンプトには、文字列の他に、様々なコンポーネントのプロンプト文字列のハッシュを渡せます。また、 :prompt を true に設定することで、一般的なプロンプトも利用できます。
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'})
静的アセットパスに「キャッシュバスター」としてタイムスタンプを追加するRailsの慣習はよく知られていると思います。これは、画像やスタイルシートなどの古いコピーが、サーバーで変更されたときにユーザーのブラウザのキャッシュから提供されないようにするためのものです。Action Viewの設定オプション cache_asset_timestamps で、この動作を変更できるようになりました。キャッシュを有効にすると、Railsは最初にアセットを提供するときにタイムスタンプを一度算出して値を保存します。これは、静的アセットを提供するための(コストのかかる)ファイルシステム呼び出しが減ることを意味しますが、その代わり、サーバーの実行中にアセットを変更しても変更がクライアントに反映されることも期待できなくなります。
エッジRailsでは、アセットホストを「呼び出しに応答する特定のオブジェクト」として宣言できるようになり、アセットホストの柔軟性が高まりました。これにより、アセットホストで必要などんな複雑なロジックも実装できるようになります。
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>
フォームのセレクタヘルパー(select や options_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?})
Rails 2.3では、キャッシュされたテンプレートを特定の環境で有効または無効にする機能があります。キャッシュされたテンプレートは、レンダリング時に新しいテンプレートファイルがあるかどうかをチェックしないので、速度が向上します。しかし、これは同時に、サーバを再起動せずに「その場で」テンプレートを置き換えられないということでもあります。
ほとんどの場合、production環境ではテンプレートのキャッシュを有効にしたいと思うでしょう。これは production.rb ファイルで設定します。
config.action_view.cache_template_loading = true
上の設定は、新しいRails 2.3アプリケーションではデフォルトで生成されます。古いバージョンのRailsからアップグレードした場合、Railsはproduction環境とtest環境ではテンプレートをキャッシュするようにデフォルトで設定しますが、development環境では設定しません。
ActiveSupport::SecureRandom によって生成されたシンプルなランダム文字列を使うようになりました。auto_link が、生成されたメールのリンクにオプション(:target や :class など)を適切に適用するようになりました。autolink ヘルパーがリファクタリングされ、より直感的に使えるようになりました。current_page? が正しく動作するようになりました。Active Supportでも、Object#tryなどいくつかの興味深い変更が行われました。
Object#try多くの人が、オブジェクトに対する操作を試みるときにtry()を使うというアイデアを採用しています。特にビューでは、<%= @person.try(:name) %>のようなコードを書くことでnilチェックを回避できるので便利です。この機能がRailsに組み込まれました。Railsに実装されたこの機能は、privateメソッドに対して NoMethodError を発生し、オブジェクトがnilの場合は常に nil を返します。
Object#tapのバックポートObject#tap は Ruby 1.9 および 1.8.7 に追加されたもので、Rails に以前からある returning メソッドに似ています。ブロックをyieldして、yieldしたオブジェクトを返すというものです。Railsは現在、これを古いバージョンのRubyでも使えるようにするコードを含んでいます。
Active SupportのXML解析サポートで、パーサーを別のものに差し替えられるようになり、柔軟性が増しました。デフォルトでは、標準的なREXMLの実装を使用しますが、適切なgemがインストールされていれば、高速なLibXMLやNokogiriの実装を自分のアプリケーションに簡単に指定できます。
XmlMini.backend = 'LibXML'
TimeWithZoneで秒以下をサポートTime クラスと TimeWithZone クラスに、時刻を XML フレンドリーな文字列で返す xmlschema メソッドが含まれました。Rails 2.3 のTimeWithZone は Time と同じ引数になり、返される文字列の小数第2位の桁数を指定できるようになりました。
Time.zone.now.xmlschema(6) # => "2009-01-16T13:00:06.13653Z"
json.orgサイトで仕様を調べると、JSON構造体のキーはすべて文字列でなければならず、二重引用符で囲まなければならないことがわかります。Rails 2.3からは、数値キーについても適切に扱うようになりました。
Enumerable#none?で、与えられたブロックにマッチする要素がないことをチェックできます。:allow_nil オプションで、ターゲットオブジェクトが nil のときに例外を発生させずにnil を返すようになりました。ActiveSupport::OrderedHashがeach_key と each_value を実装しました。ActiveSupport::MessageEncryptor は(cookieのような)信頼できない場所に保存する情報を暗号化する簡単な方法を提供します。from_xml がXmlSimple に依存しなくなりました。その代わりに、Railsは必要な機能だけを備えた、独自のXmlMini実装を含むようになりました。これにより、RailsはこれまでバンドルされていたXmlSimpleのコピーから解放されました。String#parameterize にオプションの区切り文字を渡せるようになりました。例: "Quick Brown Fox".parameterize('_') => "quick_brown_fox".number_to_phone に7桁の電話番号を渡せるようになりました。ActiveSupport::Json.decode が u0000 形式のエスケープシーケンスを処理するようになりました。上記のRackの変更に加え、Railties(Railsのコアコード)には、Rails Metal、アプリケーションテンプレート、Quiet Backtraceなど、多くの重要な変更が加えられています。
Rails Metalは、Railsアプリケーションの内部に超高速なエンドポイントを提供する新しいメカニズムです。MetalクラスはルーティングとAction Controllerをバイパスして、素の速度を提供します(もちろん、Action Controllerにあるすべてのものが使えなくなりますが)。これは、Railsを「ミドルウェアスタックを公開したRackアプリケーション」にするための最近の基礎作業の上に構築されています。Metalエンドポイントはアプリケーションやプラグインから読み込めます。
Rails 2.3には、Jeremy McAnallyによるrgアプリケーションジェネレータが組み込まれています。つまり、Railsにテンプレートベースのアプリケーション生成機能が組み込まれたということです。(他の多くのユースケースの中から)すべてのアプリケーションに含めたいプラグインのセットがある場合、テンプレートを一度セットアップしておけば、railsコマンドを実行するときにそれらが常に適用されるようになります。また、既存のアプリケーションにテンプレートを適用するrakeタスクも用意されています。
$ rake rails:template LOCATION=~/template.rb
上を実行すると、プロジェクトにすでに含まれているコードの上に、テンプレートによる変更を配置します。
thoughtbotの Quiet Backtrace プラグインはTest::Unit のバックトレースから選択的に行を削除できますが、Rails 2.3ではそれをベースにした ActiveSupport::BacktraceCleaner と Rails::BacktraceCleaner をコアに実装しています。これは、フィルタ(バックトレース行を正規表現で置換する)とサイレンサー(バックトレース行を完全に削除する)の両方をサポートします。Railsは新しいアプリケーションで最も一般的なノイズを取り除くためにサイレンサーを自動的に追加し、フィルタに追加するものを保存できるconfig/backtrace_silencers.rb ファイルを生成します。この機能により、バックトレース中の任意のgemの出力もpretty printされるようになります。
Railsの一部(とその依存関係)が実際に必要なときだけメモリに読み込まれるようにするために、かなりの作業が行われました。コアフレームワークであるActive Support、Active Record、Action Controller、Action Mailer、Action Viewは、それぞれのクラスをautoloadで遅延読み込みするようになりました。この作業によりメモリフットプリントが抑えられ、Rails全体のパフォーマンスが向上するはずです。
また、起動時にコアライブラリをオートロードするかどうかを(新しい preload_frameworks オプションで)指定できます。デフォルトの false ではRailsが少しずつオートロードされますが、一度にすべてを取り込む必要が生じることもあります(PassengerとJRubyは、Railsのすべてを一括で読み込むことを希望しています)。
様々な rake gem タスクの内部が、多くのケースでうまく動くよう大幅に改訂されました。gem システムは開発時の依存関係と実行時の依存関係の違いを認識するようになり、unpackingがより堅牢になり、gem の状態問い合わせで返される情報が改善され、スクラッチでアプリを開発するときに依存関係で「卵が先かニワトリが先か」問題を起こしにくくなりました。また、JRubyでgemコマンドを使うときや、すでにベンダリングされているgemの外部コピーを持ち込もうとする依存関係についても修正されています。
Test::Unit::TestCase から ActiveSupport::TestCase に変更され、RailsコアのテストでMochaが必須になりました。environment.rb ファイルが整理されました。Rails.root が Pathname オブジェクトを返すようになりました。つまり、 File.join を使っている 既存のコードをクリーンアップしてjoin メソッドを直接使えるようになりました。railsコマンドを実行するときに --with-dispatchers を追加すればまだ取得できますし、後から rake rails:update:generate_dispatchers で追加することも可能です)。script/server に、特定のパスからRailsアプリケーションをマウントする --path 引数を渡せるようになりました。rake gems:install が実行できないといった「卵が先かニワトリが先か」問題の多くを解決するはずです。今回のリリースで、いくつかの古いコードが非推奨化されました。
render_component が "deprecated" から "nonexistent" に変更されました。それでも必要な場合は、render_component pluginをインストールするとよいでしょう。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 の古いパーサーとの違いに起因します。リリースノート編集担当: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ガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。