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 Edgeガイド(英語のみ)を参照できるようになりました。また、ドキュメント関連では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.checkbox :_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ガイドは下記の協賛企業から継続的な支援を受けています。支援・協賛にご興味あれば協賛プランからお問い合わせいただけると嬉しいです。