Ruby on Rails 4.1 リリースノート

Rails 4.1の注目ポイント

本リリースノートでは、主要な変更についてのみ説明します。細かなバグ修正や変更については、change logを参照するか、Githubの主要なRailsリポジトリにあるコミットリスト を参照してください。

1 Rails 4.1へのアップグレード

既存のアプリケーションをアップグレードするのであれば、その前に質のよいテストカバレッジを用意するのがよい考えです。アプリケーションがRails 4.0までアップグレードされていない場合は先にそれを完了し、アプリケーションが正常に動作することを十分確認してからRails 4.1にアップデートしてください。アップグレードの注意点などについてはRuby on Railsアップグレードガイド を参照してください。

2 主要な変更

2.1 「Spring」アプリケーションプリローダー

SpringはRailsアプリケーション用のプリローダーです。アプリケーションをバックグラウンドで常駐させることで開発速度を向上させ、テストやrakeタスク、マイグレーションを実行するたびにRailsを起動しないで済むようにします。

Rails 4.1アプリケーションに含まれるbinstubは「spring化」されています。これは、アプリケーションのルートディレクトリでbin/railsおよびbin/rakeを実行すると自動的にspring環境をプリロードするということです。

rakeタスクの実行:

bin/rake test:models

Railsコマンドの実行:

bin/rails console

Springの状態確認:

$ bin/spring status
Spring is running:

1182 spring server | my_app | started 29 mins ago
3656 spring app    | my_app | started 23 secs ago | test mode
3746 spring app    | my_app | started 10 secs ago | development mode

Springのすべての機能についてはSpring READMEを参照してください。

Ruby on Railsアップグレードガイドには、この機能を既存のアプリケーションと統合する方法について記載されています。

2.2 config/secrets.yml

Rails 4.1ではconfigフォルダ内に新しくsecrets.ymlファイルが生成されます。デフォルトでは、このファイルにはアプリケーションのsecret_key_baseが含まれていますが、外部API用のアクセスキーなどの秘密キーもここに保存できます。

このファイルに保存された秘密キーはRails.application.secretsを用いてアクセスできます。 たとえば、以下のconfig/secrets.ymlについて見てみましょう。

development:
  secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
  some_api_key: SOMEKEY

上の設定にした場合、development環境でRails.application.secrets.some_api_keyを実行するとSOMEKEYが返されます。

既存のアプリケーションにこの機能を統合する方法についてはRuby on Railsアップグレードガイドを参照してください。

2.3 Action Pack Variant

スマートフォン、タブレット、デスクトップブラウザごとに異なるHTML/JSON/XMLテンプレートを使いたいことはよくあります。Variantを使うことで、これを簡単に実現できます。

リクエストvariantは、:tablet:phone:desktopのようなリクエストフォーマットを特殊化したものです。

before_actionで以下のvariantを設定できます。

request.variant = :tablet if request.user_agent =~ /iPad/

アクションの側では、フォーマットへの応答と同じ要領でvariantに応答します。

respond_to do |format|
  format.html do |html|
    html.tablet # renders app/views/projects/show.html+tablet.erb
    html.phone { extra_setup; render ... }
  end
end

フォーマットごと、variantごとに個別のテンプレートを用意してください。

app/views/projects/show.html.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html+phone.erb

以下のようなインライン文法を使うことで、variant定義を簡略化することもできます。

respond_to do |format|
  format.js         { render "trash" }
  format.html.phone { redirect_to progress_path }
  format.html.none  { render "trash" }
end

2.4 Action Mailerプレビュー

Action Mailerプレビューは、特定のURLにアクセスすることで、送信されるメールがどんなふうに見えるかをレンダリングしてプレビューします。

チェックしたいメールオブジェクトを返すメソッドを持つプレビュークラスを定義してください。

class NotifierPreview < ActionMailer::Preview
  def welcome
    Notifier.welcome(User.first)
  end
end

プレビューを表示するには http://localhost:3000/rails/mailers/notifier/welcome にアクセスします。プレビューのリストは http://localhost:3000/rails/mailers にあります。

デフォルトのプレビュークラスはtest/mailers/previewsに置かれます。 preview_pathオプションを変更することでこれを変更できます。

詳細についてはドキュメントを参照してください。

2.5 Active Record enums

データベースで値をintegerにマップしたい場所でenum属性を宣言しますが、名前でクエリを発行することもできます。

class Conversation < ActiveRecord::Base
  enum status: [ :active, :archived ]
end

conversation.archived!
conversation.active? # => false
conversation.status  # => "archived"

Conversation.archived # => Relation for all archived Conversations

Conversation.statuses # => { "active" => 0, "archived" => 1 }

詳細についてはマニュアルを参照してください。

2.6 メッセージベリファイア

メッセージベリファイア (message verifier) は、署名付きメッセージの生成と照合に利用できます。この機能は、「パスワードを保存 (remember me)」トークンや友人リストのような機密データを安全に転送するときに便利です。

Rails.application.message_verifierメソッドは、 secret_key_baseで生成されたキーで署名された新しいメッセージベリファイアと、与えられたメッセージ照合名を返します。

signed_token = Rails.application.message_verifier(:remember_me).generate(token)
Rails.application.message_verifier(:remember_me).verify(signed_token) # => token

Rails.application.message_verifier(:remember_me).verify(tampered_token)
# ActiveSupport::MessageVerifier::InvalidSignatureを発生する

2.7 Module#concerning

自然かつ堅苦しくない方法で、クラスから責任を分離します。

class Todo < ActiveRecord::Base
  concerning :EventTracking do
    included do
      has_many :events
    end

    def latest_event
      ...
    end

    private
      def some_internal_method
        ...
      end
  end
end

この例は、EventTrackingモジュールをインラインで定義し、ActiveSupport::Concernでextendし、Todoクラスにミックスインしたのと同等です。

詳細および想定されるユースケースについてはマニュアル を参照してください。

2.8 リモート <script> タグにCSRF保護を実施

JavaScriptレスポンスを伴うGETリクエストもクロスサイトリクエストフォージェリ (CSRF) 保護の対象となりました。この保護によって、第三者のサイトが重要なデータの奪取のために自分のサイトのJavaScript URLを参照して実行しようとすることを防止します。

これは、xhrを使わない場合、.js URLにヒットするすべてのテストはCSRF保護によって失敗するということです。`XmlHttpRequestsを明示的に想定するようにテストをアップグレードしてください。post :create, format: :jsの代りに、明示的にxhr :post, :create, format: :jsをお使いください。

3 Railties

変更の詳細についてはChangelog を参照してください。

3.1 削除されたもの

  • update:application_controller rake taskが削除されました。

  • 非推奨のRails.application.railties.enginesが除外されました。

  • 非推奨のthreadsafe!がRails Configから削除されました。

  • 非推奨のActiveRecord::Generators::ActiveModel#update_attributesが削除されました。ActiveRecord::Generators::ActiveModel#updateをお使いください。

  • 非推奨のconfig.whiny_nilsオプションが削除されました。

  • 非推奨のテスト実行rakeタスクrake test:uncommittedおよびrake test:recentが削除されました。

3.2 主な変更点

  • Springアプリケーションプリローダー は新規アプリケーションにデフォルトでインストールされます。Gemfileのdevelopグループにインストールされ、productionグループにはインストールされません。(Pull Request)

  • テスト失敗時にフィルタされていないバックトレースを表示するBACKTRACE環境変数。(Commit)

  • MiddlewareStack#unshiftが環境構成用に公開されました。(Pull Request)

  • メッセージベリファイアを返すApplication#message_verifierメソッド。(Pull Request)

  • デフォルトで生成されるテストヘルパーでrequireされるtest_help.rbファイルは、db/schema.rb (または db/structure.sql) を用いて自動的にテストデータベースを最新の状態に保ちます。スキーマを再度読み込んでもペンディング中のマイグレーションをすべて解決できなかった場合はエラーが発生します。config.active_record.maintain_test_schema = falseを指定することでエラーを回避できます。(Pull Request)

  • Gem::Version.new(Rails.version)を返す便利なメソッドとしてRails.gem_versionが導入されました。より信頼できるバージョン比較法を提供します。(Pull Request)

4 Action Pack

変更の詳細についてはChangelog を参照してください。

4.1 削除されたもの

  • 非推奨の、結合テスト用Railsアプリケーションフォールバックが削除されました。ActionDispatch.test_appを代りにお使いください。

  • 非推奨のpage_cache_extension configが削除されました。

  • 非推奨のActionController::RecordIdentifierが削除されました。ActionView::RecordIdentifierを代りにお使いください。

  • 以下の非推奨の定数がAction Controllerから削除されました。

削除された 今後使う
ActionController::AbstractRequest ActionDispatch::Request
ActionController::Request ActionDispatch::Request
ActionController::AbstractResponse ActionDispatch::Response
ActionController::Response ActionDispatch::Response
ActionController::Routing ActionDispatch::Routing
ActionController::Integration ActionDispatch::Integration
ActionController::IntegrationTest ActionDispatch::IntegrationTest

4.2 主な変更点

  • protect_from_forgeryによって、クロスオリジン<script>タグも利用できなくなりました。テストをアップデートして、 get :foo, format: :jsの代りにxhr :get, :foo, format: :jsを使うようにしてください。(Pull Request)

  • #url_forは、オプションのハッシュを配列の中で使えるようになりました。(Pull Request)

  • session#fetchメソッドが追加されました。この振る舞いはHash#fetchと似ていますが、戻り値が常にセッションに保存される点が異なります。(Pull Request)

  • Action ViewはAction Packから完全に分離されました。(Pull Request)

  • deep_mungeに影響されているキーがログ出力されるようになりました。(Pull Request)

  • セキュリティ脆弱性CVE-2013-0155に対応するため、パラメータのdeep_munge化を回避するconfig.action_dispatch.perform_deep_mungeconfigオプションが新たに追加されました。(Pull Request)

  • 署名及び暗号化されたcookies jarのシリアライザを指定するconfig.action_dispatch.cookies_serializerconfigオプションが新たに追加されました。 (Pull Requests 1, 2 / 詳細)

  • render :plainrender :htmlrender :bodyが追加されました。(Pull Request / 詳細)

5 Action Mailer

変更の詳細についてはChangelog を参照してください。

5.1 主な変更点

  • 37 Signals社のmail_view gemを元にメイラーのプレビュー機能が追加されました。(Commit)

  • Action Mailerメッセージの生成が計測されるようになりました。メッセージを生成するのにかかった時間がログに記録されます。(Pull Request)

6 Active Record

変更の詳細についてはChangelog を参照してください。

6.1 削除されたもの

  • SchemaCacheメソッド (primary_keystablescolumnscolumns_hash) にnilを渡す非推奨機能が削除されました。

  • 非推奨のブロックフィルタがActiveRecord::Migrator#migrateから削除されました。

  • 非推奨のStringコンストラクタがActiveRecord::Migratorから削除されました。

  • scopeで呼び出し可能オブジェクトを渡さない用法が削除されました。

  • 非推奨のtransaction_joinable=が削除されました。:joinableオプション付きでbegin_transactionをお使いください。

  • 非推奨のdecrement_open_transactionsが削除されました。

  • 非推奨のincrement_open_transactionsが削除されました。

  • 非推奨のPostgreSQLAdapter#outside_transaction?メソッドが削除されました。代りに#transaction_open?をお使いください。

  • 非推奨のActiveRecord::Fixtures.find_table_nameが削除されました。ActiveRecord::Fixtures.default_fixture_model_nameをお使いください。

  • 非推奨のcolumns_for_removeSchemaStatementsから削除されました。

  • 非推奨のSchemaStatements#distinctが削除されました。

  • 非推奨のActiveRecord::TestCaseがRailsテストスイートに移動しました。このクラスはpublicでなくなり、Railsテストの内部でのみ使われます。

  • 関連付けの:dependentで、非推奨の:restrictオプションのサポートが削除されました。

  • 関連付けにおいて、非推奨の:delete_sql:insert_sql:finder_sql:counter_sqlオプションが削除されました。

  • Columnから非推奨のtype_cast_codeが削除されました。

  • 非推奨のActiveRecord::Base#connectionメソッドが削除されました。このメソッドにはクラス経由でアクセスするようにしてください。

  • auto_explain_threshold_in_secondsにおける非推奨の警告が削除されました。

  • Relation#countから非推奨の:distinctオプションが削除されました。

  • 非推奨のpartial_updatespartial_updates?partial_updates=が削除されました。

  • 非推奨のscopedメソッドが削除されました。

  • 非推奨のdefault_scopes?が削除されました。

  • 4.0で非推奨だった、暗黙の結合参照が削除されました。

  • 依存関係としてのactiverecord-deprecated_findersが削除されました。詳細についてはgem READMEを参照してください。

  • implicit_readonlyの用法が削除されました。明示的にreadonlyメソッドを用いてレコードをreadonlyに設定してください。(Pull Request)

6.2 非推奨

  • quoted_locking_columnメソッドは非推奨です。現在使われている場所はありません。

  • ConnectionAdapters::SchemaStatements#distinctは内部で使われなくなったため非推奨です。(Pull Request)

  • rake db:test:*タスクは非推奨となりました。データベースは自動的にメンテナンスされます。railtiesのリリースノートを参照してください。(Pull Request)

  • 使われていないActiveRecord::Base.symbolized_base_class、および置き換えのないActiveRecord::Base.symbolized_sti_nameは非推奨になりました。Commit

6.3 主な変更点

デフォルトのスコープは、条件を連鎖した場合にオーバーライドされなくなりました。

今回の変更より前にモデルでdefault_scopeを定義していた場合、同じフィールドで条件が連鎖している場合にはオーバーライドされていました。現在は、他のスコープと同様、マージされるようになりました。詳細

  • モデルの属性やメソッドから派生する便利な "pretty" URL用にActiveRecord::Base.to_paramが追加されました。(Pull Request)

  • ActiveRecord::Base.no_touchingが追加されました。モデルへのタッチを無視します。(Pull Request)

  • MysqlAdapterおよびMysql2Adapterにおける型変換の真偽値が統一されました。type_casttrueの場合に1を、falseの場合に2を返します。(Pull Request)

  • .unscopeを指定するとdefault_scopeで指定された条件が削除されます。(Commit)

  • ActiveRecord::QueryMethods#rewhereが追加されました。既存の名前付きwhere条件をオーバーライドします。(Commit)

  • ActiveRecord::Base#cache_keyが拡張され、timestamp属性のリストをオプションで取れるようになりました。timestamp属性リストのうち最大値が使われます。(Commit)

  • enum属性を宣言するActiveRecord::Base#enumが追加されました。enum属性はデータベースのintegerにマップされますが、名前でクエリできます。(Commit)

  • json値が書き込み時に型変換されます。これにより値がデータベースからの読み出し時と一貫します。(Pull Request)

  • hstore値が書き込み時に型変換されます。これにより値がデータベースからの読み出し時と一致します。(Commit)

  • サードパーティ製ジェネレータ用に、next_migration_numberがアクセス可能になりました。(Pull Request)

  • 引数をnilにしてupdate_attributesを呼び出すと、常にArgumentErrorエラーが発生します。具体的には、渡された引数がstringify_keysに応答しない場合にエラーが発生します。(Pull Request)

  • CollectionAssociation#first/#last (has_manyなど) による結果の取り出しで、コレクション全体を読み出すクエリの代りに、限定的なクエリが使われるようになりました。(Pull Request)

  • Active Recordモデルクラスのinspectは新しい接続を初期化しなくなりました。つまり、データベースが見つからない状態でinspectを呼び出した場合に例外を発生しなくなりました。(Pull Request)

  • countのカラム制約が削除されました。SQLが無効な場合にはデータベース側でraiseされます。(Pull Request)

  • Railsが逆関連付けを自動で検出するようになりました。関連付けで:inverse_ofオプションを設定していない場合、Active Recordはヒューリスティックに逆関連付けを推測します。(Pull Request)

  • ActiveRecord::Relationの属性のエイリアスを扱うようになりました。シンボルキーを使うと、ActiveRecordはエイリアス化された属性名をデータベース上の実際のカラム名に翻訳します。(Pull Request)

  • フィクスチャーのERBファイルはメインオブジェクトのコンテキストでは評価されなくなりました。複数のフィクスチャーで使われているヘルパーメソッドは、ActiveRecord::FixtureSet.context_classでインクルードされるモジュール上で定義しておく必要があります。(Pull Request)

  • RAILS_ENVが明示的に指定されている場合はテストデータベースのcreateやdropは行いません。(Pull Request)

Relationには#map!#delete_ifなどのミューテーターメソッド (mutator method) が含まれなくなりました。これらのメソッドを使いたい場合は#to_aを呼び出してArrayに変更してからにしてください。(Pull Request)

  • find_in_batchesfind_eachResult#eachEnumerable#index_byは、自身のサイズを計算可能なEnumeratorを返すようになりました。(Pull Request)

  • scopeenumとAssociationsで "dangerous" 名前衝突が発生するようになりました。(Pull Request, Pull Request)

  • secondからfifthメソッドはfirstファインダーと同様に動作します。(Pull Request)

  • touchafter_commitafter_rollbackコールバックを発火するようになりました。(Pull Request)

  • sqlite >= 3.8.0でのパーシャルインデックスが有効になりました。(Pull Request)

  • change_column_nullが復元可能になりました。(Commit)

  • マイグレーション後無効になったスキーマダンプにフラグが追加されました。これは新しいアプリケーションのproduction環境ではデフォルトでfalseに設定されます。(Pull Request)

7 Active Model

変更の詳細についてはChangelog を参照してください。

7.1 非推奨

  • Validator#setupは非推奨です。今後はバリデーターのコンストラクタ内で手動で行なう必要があります。(Commit)

7.2 主な変更点

  • ActiveModel::Dirtyに、状態を制御する新しいAPIreset_changes およびchanges_appliedが追加されました。

  • 検証の定義時に複数のコンテキストを指定できるようになりました。(Pull Request)

  • attribute_changed?がハッシュを受け付けるようになり、属性が与えられた値変更されたか(または与えられた値から変更されたか)どうかをチェックするようになりました。(Pull Request)

8 Active Support

変更の詳細についてはChangelog を参照してください。

8.1 削除されたもの

  • MultiJSON依存が削除されました。これにより、ActiveSupport::JSON.decodeMultiJSONのオプションハッシュを受け付けなくなりました。(Pull Request / 詳細)

  • カスタムオブジェクトをJSONにエンコードするencode_jsonフックのサポートが削除されました。この機能はactivesupport-json_encoder gemに書き出されました。 この機能はactivesupport-json_encoder gemに書き出されました。

  • 非推奨のActiveSupport::JSON::Variableが代替なしで削除されました。

  • 非推奨のString#encoding_aware?コアエクステンション (core_ext/string/encoding) が削除されました。

  • 非推奨のModule#local_constant_namesが削除されました。Module#local_constantsをお使いください。

  • 非推奨のDateTime.local_offsetが削除されました。DateTime.civil_from_formatをお使いください。

  • 非推奨のLoggerコアエクステンション (core_ext/logger.rb) が削除されました。

  • 非推奨のTime#time_with_datetime_fallbackTime#utc_timeTime#local_timeが削除されました。Time#utcおよびTime#localをお使いください。

  • 非推奨のHash#diffが代替なしで削除されました。

  • 非推奨のDate#to_time_in_current_zoneが削除されました。Date#in_time_zoneをお使いください。

  • 非推奨のProc#bindが代替なしで削除されました。

  • 非推奨のArray#uniq_byArray#uniq_by!が削除されました。ネイティブのArray#uniqおよびArray#uniq!をお使いください。

  • 非推奨のActiveSupport::BasicObjectが削除されました。ActiveSupport::ProxyObjectをお使いください。

  • 非推奨のBufferedLoggerが削除されました。ActiveSupport::Loggerをお使いください。

  • 非推奨のassert_presentメソッドとassert_blankメソッドが削除されました。assert object.blank?およびassert object.present?をお使いください。

  • フィルタオブジェクト用の非推奨#filterメソッドが削除されました。対応する別のメソッドをお使いください。(before filterの#beforeなど)

  • デフォルトの活用形から不規則活用の'cow' => 'kine'が削除されました。(Commit)

8.2 非推奨

  • 時間表現Numeric#{ago,until,since,from_now}が非推奨になりました。この値はAS::Durationに明示的に変換してください。例: 5.ago => 5.seconds.ago (Pull Request)

  • requireパスactive_support/core_ext/object/to_jsonが非推奨になりました。active_support/core_ext/object/jsonを代りにrequireしてください。(Pull Request)

  • ActiveSupport::JSON::Encoding::CircularReferenceErrorが非推奨になりました。この機能はactivesupport-json_encoder gemに書き出されました。(Pull Request / 詳細)

  • ActiveSupport.encode_big_decimal_as_stringオプションが非推奨になりました。この機能はactivesupport-json_encoder gemに書き出されました。 (Pull Request / 詳細)

  • カスタムのBigDecimalシリアライズが非推奨になりました。(Pull Request)

8.3 主な変更点

  • ActiveSupportのJSONエンコーダーが書き直され、pure-RubyのカスタムエンコーディングではなくJSON gemを利用するようになりました。 (Pull Request / 詳細)

  • JSON gemとの互換性が向上しました。 (Pull Request / 詳細)

  • ActiveSupport::Testing::TimeHelpers#travelおよび#travel_toが追加されました。これらのメソッドは、Time.nowおよびDate.todayをスタブ化することによって、現在時刻を指定の時刻または時間に変換します。

  • ActiveSupport::Testing::TimeHelpers#travel_backが追加されました。このメソッドは、travelおよびtravel_toメソッドによって追加されたスタブを削除することで、現在時刻を元の状態に戻します。(Pull Request)

  • Numeric#in_millisecondsが追加されました。1.hour.in_millisecondsのように利用でき、これをgetTime()などのJavaScript関数に渡すことができます。(Commit)

  • Date#middle_of_dayDateTime#middle_of_dayTime#middle_of_dayメソッドが追加されました。エイリアスとしてmiddaynoonat_middayat_noonat_middle_of_dayも追加されました。(Pull Request)

  • 期間を生成するためのDate#all_week/month/quarter/yearが追加されました。(Pull Request)

  • Time.zone.yesterdayTime.zone.tomorrowが追加されました。(Pull Request)

  • よく使われるString#gsub("pattern,'')の省略表現としてString#remove(pattern)が追加されました。(Commit)

  • 値がnilの項目をハッシュから削除するためのHash#compactおよびHash#compact!が追加されました。(Pull Request)

  • blank?およびpresent?はシングルトンを返します。(Commit)

  • 新しいI18n.enforce_available_locales configのデフォルトはtrueです。これは、ロケールに渡されたI18navailable_localesリストに載っていなければならないということです。(Pull Request)

Module#concerningが導入されました。自然かつ堅苦しくない方法で、クラスから責任を分離します。(Commit)

  • Object#presence_inが追加されました。値を単に許可済みリストに追加します。(Commit)

9 クレジット表記

膨大な時間を費やしてRailsを作り、頑丈かつ安定したフレームワークにしてくれた多くの皆様については、Railsコントリビューターの完全なリストを参照してください。これらの方々全員に敬意を表明いたします。