Rails 3.2 リリースノートを翻訳してみました

Rails 3.2 リリースノートを翻訳してみました

こんにちは、ほりいです。風邪が流行っていて体調管理が大変なシーズンですね。

先週 Rails 3.2.0 がリリースされました ね。
Rails を使った Web 開発チームでは 3.2 を使い始めていますが、社内でも結局どう変わるの? という声がありましたので、勉強がてらみんなで Ruby on Rails 3.2 Release Notes を翻訳してみようという試みを行いました。その成果を公開したいと思います。

注意書き:

  • 1章「Upgrading to Rails 3.2」と 12章「Credits」は省略していますので原文を参照ください。
  • 内容は無保証です。逆のことを書いていても泣かない。僕は泣きますが。
  • 実はリリース前に翻訳をやったので抜けがあるかもしれません。

2. Rails 3.2 のアプリケーションを作る

# rubygem 'rails' がインストールされている必要があります
$ rails new myapp
$ cd myapp

2.1 Gem をベンダーするには

現在、Rails はアプリケーションを起動するために必要な gem は、アプリケーションの root に置いた Gemfile によって決められます。
GemfileBundler という gem によって処理され、全ての依存する gem をインストールします。また、全ての依存する gem をアプリケーションにローカルインストールすることもできます。その場合、システムインストールした gem に依存することはありません。

詳しい情報: Bundlerのホームページ

2.2 Edge で生きる

BundlerGemfile は、専用の bundle コマンドで Rails アプリケーションをとても簡単に freeze します。もし Git リポジトリから直接 bundle したいときは、 --edge フラグを追加してください。

$ rails new myapp --edge

もしローカルにチェックアウトした Rails のリポジトリがあって、それを使ってアプリケーションを生成したい場合は、 —dev フラグを追加します。

$ ruby /path/to/rails/bin/rails new myapp --dev

3. 主な機能

3.1 高速な development モードとルーティング

Rails3.2 のdevelopment モードは特筆すべき速さになりました。 Active Reload にインスパイアされて、 Rails は実際にファイルが変更された時のみクラスを再読み込みするようになりました。大規模なアプリケーションでのパフォーマンスの改善は劇的です。ルーティングの認識も Journey のおかげでだいぶ速くなりました。

3.2 自動クエリ表示

Rails3.2 には ARel に生成されたクエリを表示する便利な機能がつきました。これは ActiveRecord::Relation に実装された explain というメソッドによるものです。たとえば、 puts Person.active.limit(5).explain といったコードを実行すると、 ARel が生成するクエリが表示されます。これによってインデックスが正しいかどうかの確認、さらなるクエリ最適化が可能です。
0.5 秒以上かかるクエリは development モードでは自動的に表示されます。この閾値はもちろん変更可能です。

3.3 タグつきのログ

複数ユーザー、複数アカウントのアプリケーションを動かしている時、「誰がやったか」によってログをフィルタリングできると、とても便利です。 ActiveSupport の TaggedLogging はサブドメイン、リクエスト ID 等々をログにスタンプすることでそれを実現し、この手のアプリのデバッグをしやすくしました。

4 ドキュメンテーション

Rails 3.2 から、 Rails guides は Kindle や、iPad、iPhone、Mac、Android などのフリーの Kindle リーダーアプリケーションで利用できるようになりました。

5 Railties

  • 依存関係のあるファイルに変更があったときのみクラスを再読み込みするようになり、開発速度が向上しました。この機能は config.reload_classes_only_on_changefalse とすることで無効にできます。
  • 新規作成したアプリケーションの設定ファイルには config.active_record.auto_explain_threshold_in_seconds というフラグがあります。development.rb には 0.5 と設定してあり、 production.rb ではコメントアウトしています。test.rb には記述していません。
  • 例外発生時に ShowException ミドルウェアに呼ばれる例外処理アプリケーションを設定するために config.exceptions_app を追加しました。
  • DebugExceptions ミドルウェアを追加しました。これは ShowExceptions ミドルウェアから抽出された機能を含みます。
  • rake routes に、マウントしている engine のルーティングを表示するようにしました。
  • railties の読み込み順を、 config.railties_order を使って変更できるようにしました。たとえば:
    config.railties_order = [Blog::Engine, :main_app, :all]
  • Scaffold は、内容を返さない API リクエストには 204 No Content を返すようになりました。これで Scaffold は jQuery からもすぐに使えるようになりました。
  • Rails::Rack::Logger ミドルウェアを更新し、config.log_tags に任意のタグセットを書いて ActiveSupport::Taggedlogging に与えることができるようになりました。これにより簡単にログの行にサブドメインやリクエストID(これらは多数のユーザーが利用する公開アプリケーションでとても便利)といったデバッグ情報のタグを埋め込めるようになりました。
  • rails new コマンドのデフォルトオプションを ~/.railsrc に書くことができるようになりました。
  • destroy コマンドのエイリアスとして d と書けるようになりました。これは Engine でも動作します。
  • Scaffold や Model のジェネレータの属性のデフォルトを string にしました。このように書けるようになりました: rails g scaffold Post title body:text author
  • scaffold/model/migration のジェネレータに “index” および “uniq” という修飾子を与えられるようになりました。たとえば,
    rails g scaffold Post title:string:index author:uniq price:decimal{7,2}

    これは title および author にそれぞれ index および unique index を作成します。また decimal のような一部の型では、カスタムオプションを受け付けます。この例では、 price は 整数部および小数部の桁数がそれぞれ 7, 2 となる decimal 型のカラムになります。

  • 古いプラグインのジェネレータ rails generate plugin は削除されました。 rails plugin new を利用してください。
  • 古い config.paths.app.controller API は削除されました。 config.paths["app/controller"] を利用してください。

5.1 廃止・非推奨

Rails::Plugin は廃止予定になり、 Rails 4.0 で削除される予定です。 vendor/plugins にプラグインを追加する代わりに、 gem を使うか、パスと一緒に Bundler を使うか、git dependencies を使ってください。

6 Action Mailer

  • mail のバージョンを 2.4.0 に引き上げました。
  • Rails 3.0 で廃止予定になっていた古い Action Mailer の API を削除しました。

7 Action Pack

7.1 Action Controller

  • ActiveSupport::Benchmarkable が、ActionController::Base のデフォルトモジュールとして作られました。これにより、#benchmark メソッドはかつて使われていたように、コントローラのコンテキストでもう一度有効になりました。
  • :gzip オプションが caches_page に追加されました。 デフォルトオプションは、 page_cache_compression を使うことでグローバルに変更可能です。
  • :only 、:except 条件を付けてlayoutを記述し、それらの条件を満たさなかった場合、 Rails はあなたのデフォルトレイアウト(例えば “layouts/application” のような)を使うようになります。
    class CarsController
      layout 'single_car', :only => :show
    end
    

リクエストが :show アクションに届いたとき、 Rails は layouts/single_car を使い、その他のアクションにリクエストが届いたときには、layoutes/application を(もしくは、もしあれば layouts/cars を)使います。

  • form_for は :as オプションが付いている場合には css の class および id に "#{action}_#{as}" を使うように変わりました。以前のバージョンは "#{as}_#{action}" を使っていました。
  • ActiveRecord モデルの ActionController::ParamsWrapper は、attr_accessible 属性がセットされている場合、単にそれらをラップするだけになりました。そうでない場合は、クラスメソッド attribute_names によって返される属性のみがラップされます。これは、属性を attr_accessible に追加することによりネストされた属性のラッピングを修正します。
  • コールバックが停止する前に、毎回 “Filter chain halted as CALLBACKNAME rendered or redirected” というログを出すようになりました。
  • ActionDispatch::ShowExceptions はリファクタされました。コントローラは例外の表示非表示の選択を担当するようになります。コントローラの show_detailed_exceptions? は、どのリクエストをエラーにおけるデバッグ情報に配信するかを規定していますが、これはオーバーライド可能です。コントローラーでこのメソッドをオーバーライドすることで、どのリクエストでエラー時のデバッグ情報を表示するかを指定できます。
  • API リクエストに対してレスポンス本文が存在しない場合(たとえば新しい scaffold の場合)、レスポンダは 204 No Content を返します。
  • ActionController::TestCase cookies はリファクタされました。テストケースで cookie を入れる場合、cookies[] を使うことができるようになりました。
    cookies[:email] = 'user@example.com'
    get :index
    assert_equal 'user@example.com', cookies[:email]
    

cookie を消すには、clear を使います。

cookies.clear
get :index
assert_nil cookies[:email]

HTTP_COOKIE を書くことはなくなり、cookie jar はリクエスト中存続するため、もしテストのために環境を操作する必要があるなら、cookie jar が作られる前にこの作業を行う必要があります。

  • :type を指定していない場合、send_file は拡張子から MIME タイプを推測します。
  • PDF, ZIP, その他の MIME タイプが追加されました。
  • レコード取得のための fresh_when/stale? が、オプションハッシュの代わりに使えるようになりました。
  • CSRF トークンが欠けている場合に警告を出すログレベルを、 :debug から :warn に変更しました。
  • Assets は、デフォルトではリクエストと同じプロトコルを使うか、 リクエストを使えない場合は相対プロトコルを使います。

7.1.1 廃止・非推奨

  • 親のクラスで layout がセットされているコントローラーが、暗黙で layout を検索する挙動は廃止されました。
class ApplicationController
  layout "application"
end
class PostsController < ApplicationController
end

上の例では、Posts コントローラが自動的に posts レイアウトを探すことはなくなりました。もしこの機能が必要であれば、 layout "application" を ApplicationController から消すか、 PostsController 内で明示的に nil をセットすることで実現できます。

  • ActionController::UnknownAction は廃止予定です。代わりに AbstractController::ActionNotFound を使用してください。
  • ActionController::DoubleRenderError は廃止予定です。代わりに AbstractController::DoubleRenderError を使用してください。
  • アクションが見つからない場合に method_missing を使うことは推奨しません。代わりに action_missing を使用してください。
  • ActionController#rescue_action, ActionController#initialize_template_class, ActionController#assign_shortcuts は廃止予定です。

7.2 Action Dispatch

  • config.action_dispatch.default_charset を追加しました。ActionDispatch::Response のデフォルトの文字セットを設定可能です。
  • ActionDispatch::RequestId ミドルウェアを追加しました。一意の X-Request-Id ヘッダーがレスポンスで利用できるようになり、また ActionDispatch::Request#uuid メソッドで使用できます。これでスタックでリクエストを End-to-End にトレースしたり、Syslog のような混合のログで個々のリクエストを識別することが簡単になります。
  • ShowExceptionet ミドルウェアは、アプリケーションがエラーを起こしたときに例外内容を出力するためのアプリケーションを受け取ることができます。このアプリケーションは env[“action_dispatch.exception”] にコピーされた例外とステータスコードに書き換えられた PATH_INFO を渡して実行されます。
  • rescue responses は railtie で config.action_dispatch.rescue_responses 経由で設定可能になりました。

7.2.1 廃止・非推奨

  • デフォルトの文字セットをコントローラーレベルで設定することは非推奨になりました。新しい config.action_dispatch.default_charset を使用してください。

7.3 Action View

  • ActionView::Helpers::FormBuilder で button_tag を追加しました。このメソッドは submit_tag のデフォルトの挙動に似ています。
    <%= form_for @post do |f| %>
      <%= f.button %>
    <% end %>
    
  • 日付のヘルパーメソッドは新しいオプション :use_two_digit_numbers => true を受け付けます。これは実際の value を変えずに、頭の0がついている月と日のセレクトボックスを描画します。具体的には ISO 8601 形式の日付 (例えば 2011-08-01 )のような表示を行う場合に有用です。
  • フォームに名前空間を与えることができるようになりました。これはフォームの要素の ID 属性が一意であることを保証するためです。この名前空間属性の値はアンダースコアとともに生成された HTML の id 属性の先頭に追加されます。
    <%= form_for(@offer, :namespace => 'namespace') do |f| %>
      <%= f.label :version, 'Version' %>:
      <%= f.text_field :version %>
    <% end %>
  • select_year で生成する option の数が 1000 に制限されました。:max_years_allowed オプションによってこの制限を変更できます。
  • content_tag_for と div_for は引数にレコードの集合を取れるようになりました。もしブロックで引数を受け取るようにしていれば、第一引数に各レコードが与えられます。このため、こうする代わりに:
@items.each do |item|
  content_tag_for(:li, item) do
     Title: <%= item.title %>
  end
end

このようにすることができます:

content_tag_for(:li, @items) do |item|
  Title: <%= item.title %>
end
  • font_path ヘルパーが追加されました。これは public/fonts にあるフォントアセットのパスを導出します。

7.3.1 廃止・非推奨

  • render :template => "foo.html.erb" のように、:template やその類にフォーマットやハンドラを渡す方式は廃止されました。そのかわり、 :handlers と :formats をオプションとして次のように直接渡すことができます。 render :template => “foo”, :formats => [:html, :js], :handlers => :erb

7.4 Sprockets

  • Sprockets のログ処理のための、config.assets.logger オプションを追加しました。これを false にすることでログをオフにし、 nil を与えることで デフォルトの Rails.logger の設定に準じるようになります。

8 Active Record

  • 真偽値カラムの ‘on’ と ‘ON’ は true にキャストされます。
  • timestampscreated_atupdated_at をデフォルトでは NOT NULL 制約付きで生成するようになりました。
  • ActiveRecord::Relation#explain が実装されました。
  • ブロック内で自動的に EXPLAIN を無効化させるかユーザーが選択できる AR::Base.silence_auto_explain が実装されました。
  • スロークエリを自動的にロギングする EXPLAIN が実装されました。新しい設定値の config.active_record.auto_explain_threshold_in_seconds によりスロークエリを判断します。nil に設定すればこの機能は無効化されます。development mode でのデフォルトは 0.5 で、test mode, production mode では nil です。Rails 3.2 では SQLite, MySQL (mysql2 adapter), PostgreSQL でこの機能をサポートします。
  • シンプルな単一のカラムの key/value ストアを宣言する ActiveRecord::Base.store を追加しました。
    class User < ActiveRecord::Base
      store :settings, accessors: [ :color, :homepage ]
    end
    u = User.new(color: 'black', homepage: '37signals.com')
    u.color                          # Accessor stored attribute
    u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
    
  • 与えられたスコープのみで migration を実行する機能を追加しました。これにより1つの engine からのみ migration を実行できます。(たとえば、削除する必要のある engine による変更を元に戻す場合。)
    rake db:migrate SCOPE=blog
    
  • engine からコピーされた migration はエンジン名のスコープを持つようになりました。たとえば、 01_create_posts.blog.rb です。
  • 直接内在するテーブルからカラム値の配列を返す ActiveRecord::Relation#pluck メソッドが実装されました。これはシリアライズされた属性にも動作します。
    Client.where(:active => true).pluck(:id)
    # SELECT id from clients where active = 1
    
  • オーバーライド、コンポジションができるように単独のモジュール内に associated methods が生成されます。MyModel という名前のクラスの場合、モジュール名は MyModel::GeneratedFeatureMethods です。Active Model 内で generated_attributes_methods モジュールが定義された後すぐにモデルクラス内に組み込まれますので、associated methods は同名の attribute methods をオーバーライドします。
  • ユニークなクエリを生成する ActiveRecord::Relation#uniq を追加しました。
    Client.select('DISTINCT name')
    

    以下のようにも書けます :

    Client.select(:name).uniq
    

    これはリレーション内のユニーク性を取り消します :

    Client.select(:name).uniq.uniq(false)
    
  • SQLite、MySQL、PostgreSQL アダプタで index sort order をサポートします。
  • アソシエーションのための :class_name オプションは string の代わりに symbol をとれるようになりました。これは初心者の混乱を避けるためと、:foreign_key のような既に symbol でも string でもとることが可能な現状との一貫性のためです。
    has_many :clients, :class_name => :Client # Note that the symbol need to be capitalized
    
  • development mode では、db:drop は db:create と対称的な順に test データベースもドロップします。
  • MySQL で大文字小文字を無視する照合方法を使用しているカラムの場合には、ユニークかどうかのバリデーションで LOWER を使用しません。
  • transactional fixtures はすべての有効なデータベース接続を使えます。transactional fixtures を無効にせずに異なる接続を利用して model をテストすることができます。
  • first_or_create, first_or_create!, first_or_initialize を Active Record に追加しました。これは引数が、レコードの検索のため、もしくは作成のためのどちらに使われているのかより明快になるので、find_or_create_by ダイナミックメソッドより良いアプローチです。
    User.where(:first_name => "Scarlett").first_or_create!(:last_name => "Johansson")
    

8.1 廃止・非推奨

  • スレッド内での接続自動クローズは廃止予定になりました。たとえば以下のコードは非推奨です:
    Thread.new { Post.find(1) }.join
    

    スレッドの終わりにクローズするように変更しなければなりません。

    Thread.new {
      Post.find(1)
      Post.connection.close
    }.join
    

    アプリケーションコード内でスレッドを実行している人のみがこの変更に配慮する必要があります。

  • set_table_name, set_inheritance_column, set_sequence_name, set_primary_key, set_locking_column メソッドは廃止予定になりました。代わりに代入メソッドを使用してください。たとえば、set_table_name の代わりには self.table_name= を使用してください。
    class Project < ActiveRecord::Base
      self.table_name = "project"
    end
    

    もしくは、自身で self.table_name を定義してください :

    class Post < ActiveRecord::Base
      def self.table_name
        "special_" + super
      end
    end
    Post.table_name # => "special_posts"
    

9 Active Model

  • ActiveModel::Errors#added? により定義されたエラーが発生したかどうかチェックできます。
  • strict => true により失敗したときに常に例外を発生させるような厳格なバリデーションが定義可能です。
  • サニタイザの振る舞いを変更するための簡単な API として mass_assignment_sanitizer が提供されます。振る舞いとしては :logger (default) と :strict がサポートされています。

9.1 廃止・非推奨

  • ActiveModel::AttributeMethods の define_attr_method は廃止予定になりました。これは Active Record の set_table_name のようなメソッドをサポートするためだけに存在していますが、それらのメソッドはすでに廃止予定になっています。
  • Model.model_name.partial_path は廃止予定になりました。かわりに model.to_partial_path を利用してください。

10 Active Resource

  • リダイレクトレスポンス: 303 See Other や 307 Temporary Redirect が返ってきた時も、 301 Moved Permanently や 302 Found が返ってきたときと同様の挙動になりました。

11 Active Support

  • ActiveSupport:TaggedLogging を追加しました。これは任意の標準 Logger クラスをラップし、タグ付け機能を付与することができます。
    Logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
    Logger.tagged("BCX") { Logger.info "Stuff" }
    # Logs "[BCX] Stuff"
    Logger.tagged("BCX", "Jason") { Logger.info "Stuff" }
    # Logs "[BCX] [Jason] Stuff"
    Logger.tagged("BCX") { Logger.tagged("Jason") { Logger.info "Stuff" } }
    # Logs "[BCX] [Jason] Stuff"
    
  • Date, Time, DateTime の beginning_of_week メソッドは、週の開始曜日を指定するオプションを付けられるようになりました。
  • ActiveSupport::Notifications.subscribed を追加しました。与えたブロックが実行されている間のみの受信登録 (subscription) が可能です。
  • 新しいメソッド Module#qualified_const_defined?, Module#qualified_const_get and Module#qualified_const_set はほぼ同名の標準 API と同じですが、(モジュールの)修飾付きの定数名を扱うことができます。
  • #demodulize と対になる #deconstantize を追加しました。このメソッドは修飾付きの定数名の最も右の部分を取り除きます。
  • safe_constantize を追加しました。constantize と同様に文字列を定数化しますが、その定数(またはその定数の一部)が未定義であった場合に、例外を投げるかわりに nil を返します。
  • Array#extracted_options! で ActiveSupport::OrderedHash を抽出できるようになりました。
  • Array#prepend を Array#unshift のエイリアスとして追加しました。また Array#append を Array#<< のエイリアスとして追加しました。
  • Ruby 1.9 における空白文字列 (blank?) の定義は Unicode ホワイトスペース文字に拡張されました。同様に、 Ruby 1.8 においては ideographic space U+3000 が空白文字とみなされるようになりました。
  • inflector は頭字語 (acronym) を使えるようになりました。
  • 範囲を生成する方法として Time#all_day, Time#all_week, Time#all_quarter そして Time#all_year を追加しました。
    Event.where(:created_at => Time.now.all_week)
    Event.where(:created_at => Time.now.all_day)
  • Class#cattr_accessor や同種のメソッドのオプションに instance_accessor: false を指定できるようになりました。
  • ActiveSupport::OrderedHash は、#each や #each_pair で与えられたブロックが splat(*で展開される変数) 付きの変数でパラメータを受け付ける場合に、その挙動が変更されました。
  • ActiveSupport::Cache::NullStore を、開発やテスト向けに追加しました。
  • ActiveSupport::SecureRandom は削除されました。標準ライブラリの SecureRandom を使ってください。

11.1 廃止・非推奨

  • ActiveSupport::Base64 は廃止予定です。 ::Base64 を使ってください。
  • ActiveSupport::Memoizable は廃止予定です。 Ruby の memoization pattern を使ってください。
  • Module#synchronize は廃止予定で、代替手段はありません。Ruby の標準 monitor ライブラリを使ってください。
  • ActiveSupport::MessageEncryptor#encrypt と ActiveSupport::MessageEncryptor#decrypt は廃止予定です。
  • ActiveSupport::BufferedLogger#silence は廃止予定です。あるブロック内でログを潰したい場合には、そのブロック内でログレベルを変更してください。
  • ActiveSupport::BufferedLogger#open_log は廃止予定です。そもそもこのメソッドは public であるべきではありません。
  • ActiveSupport::BufferedLogger のログファイルを置くディレクトリを自動で生成する挙動は非推奨になりました。ログファイルを生成する前にディレクトリを作成しておくようにしてください。
  • ActiveSupport::BufferedLogger#auto_flushing は廃止予定です。
    こんなふうに下のファイルハンドルに同期レベルを設定するか、ファイルシステムをチューニングしてください。現在ではファイルシステムのキャッシュはフラッシュをコントロールできます。

    f = File.open('foo.log', 'w')
    f.sync = true
    ActiveSupport::BufferedLogger.new f
    
  • ActiveSupport::BufferedLogger#flush は廃止予定です。ファイルハンドルに同期を設定するか、ファイルシステムをチューニングしてください。

追記

この記事を出したと思ったら Rails 3.2.1 がリリースされました ので、 CHANGELOGs gist の日本語訳 も作ってみました。
でも https://github.com/rails/rails/compare/v3.2.0…v3.2.1 を見るのが早いかもしれません。

——

interpreters: @ffu_ , @shishi4tw , @1048_t , @h_demon , @holysugar