1 一般的なアドバイス
言うまでもないことですが、既存のアプリケーションをアップグレードする際には、何のためにアップグレードするのかをはっきりさせておく必要があります。新しいバージョンのうちどの機能が必要になるのか、既存のコードのサポートがどのぐらい困難になるのか、アップグレードに必要な時間とスキルはどれほど必要かなど、いくつもの要素を調整しなければなりません。
1.1 テスティングのカバレッジ
アップグレード後にアプリケーションが正常に動作していることを確認する方法としては、良いテストカバレッジをアップグレード前に準備しておくのが最善です。アプリケーションを一気に検査する自動テストがないと、変更点をすべて手動で確認しなければならず膨大な時間がかかってしまいます。Railsのようなアプリケーションの場合、これはアプリケーションのあらゆる機能を一つ残らず確認しなければならないということです。アップグレードの実施は、テストカバレッジをきちんと準備してから行なうよう、お願いいたします。
1.2 アップグレード手順
Rails のバージョンを変更する場合、マイナーバージョンを1つずつゆっくりと変更して、非推奨機能の警告をすべて確認・利用するのが最善の方法であると言えます。言い換えると、アップグレードを急ぐあまりバージョンをスキップするべきではありません。Rails のバージョン番号は「メジャー番号.マイナー番号.パッチ番号」の形式を取ります。メジャーバージョンやマイナーバージョンが変更される場合、公開 API の変更によるエラーがアプリケーションで発生する可能性があります。パッチバージョンはバグ修正のみが含まれ、公開 API 変更は含まれません。
アップグレードは以下の手順で行います。
- テストを書き、テストがパスすることを確認する。
- 現時点のバージョンのパッチバージョンを最新のパッチに移行する。
- テストを修正し、非推奨の機能を修正する。
- 次のマイナーバージョンの最新パッチに移行する。
上の手順を繰り返して、最終的にRailsを目的のバージョンにアップグレードします。バージョンを移行するたびに、Gemfile 内の Rails バージョン番号を変更(これに伴い、他の gem のバージョン変更が必要になることもあります)し、bundle update
を実行する必要があります。続いて、以下のアップデートタスクを実行して設定ファイルをアップデートし、テストを実行します。
リリース済みの Rails バージョンのリストはここで確認できます。
1.3 Rubyのバージョン
Railsは、そのバージョンがリリースされた時点で最新のバージョンのRubyに依存しています。
- Rails 5 では Ruby 2.2.2 以降が必須です。
- Rails 4ではRuby 2.0が推奨されます。Ruby 1.9.3以上が必須です。
- Rails 3.2.xはRuby 1.8.7の最終ブランチです。
- Rails 3以上では、Ruby 1.8.7以降が必須です。これより古いRubyのサポートは公式に停止しています。できるだけ早くアップグレードをお願いします。
Ruby 1.8.7 p248およびp249にはRailsをクラッシュさせるマーシャリングバグがあります。Ruby Enterprise Editionでは1.8.7-2010.02以降このバグは修正されています。Ruby 1.9系を使用する場合、Ruby 1.9.1はあからさまなセグメンテーション違反が発生するため使用できません。1.9.3をご使用ください。
1.4 アップデートタスク
Rails ではapp:update
というタスクが提供されています (Rails 4.2 以前では rails:update
という名前でした)。Gemfileに記載されているRailsのバージョンを更新後、このタスクを実行することで、新しいバージョンでのファイル作成や既存ファイルの変更を対話形式で行うことができます。
$ rails app:update identical config/boot.rb exist config conflict config/routes.rb Overwrite /myapp/config/routes.rb? (enter "h" for help) [Ynaqdh] force config/routes.rb conflict config/application.rb Overwrite /myapp/config/application.rb? (enter "h" for help) [Ynaqdh] force config/application.rb conflict config/environment.rb ...
予期しなかった変更が発生した場合は、必ず差分を十分にチェックしてください。
2 Rails 5.0からRails 5.1へのアップグレード
Rails 5.1 の変更点の詳細はリリースノートを参照してください。
2.1 トップレベルのHashWithIndifferentAccess
が弱く非推奨化された
アプリでトップレベルのHashWithIndifferentAccess
クラスを使っている場合、すぐでなくてもよいのでActiveSupport::HashWithIndifferentAccess
に置き換えてください。
これは「弱い非推奨化」であり、しばらくは正常に動作し、非推奨警告も表示されません。ただし、この定数は将来削除されます。
また、こうしたオブジェクトのダンプを含むかなり古いYAMLドキュメントがある場合は、YAMLを再度読み込み/ダンプして、正しい定数が参照されるようにしておく必要があるかもしれません。また、読み込みについては今後も行えます。
2.2 application.secrets
ですべてのキーをシンボルとして読み込むようになった
config/secrets.yml
に保存されているアプリの設定がネストしている場合、すべてのキーがシンボルとして読み込まれます。このため、文字列による設定へのアクセス方法を以下のように変更する必要があります。
変更前:
Rails.application.secrets[:smtp_settings]["address"]
変更後:
Rails.application.secrets[:smtp_settings][:address]
3 Rails 4.2からRails 5.0へのアップグレード
Rails 5.0 の変更点の詳細はリリースノートを参照してください。
3.1 Ruby 2.2.2以上が必須
Ruby on Rails 5.0 以降は、バージョン 2.2.2 以降の Ruby だけをサポートします。 Ruby のバージョンが 2.2.2 以降であることを確認してから手順を進めてください。
3.2 Active Record モデルは今後デフォルトで ApplicationRecord を継承する
Rails 4.2 の Active Record モデルは ActiveRecord::Base
を継承していました。Rails 5.0 では、すべてのモデルが ApplicationRecord
を継承するようになりました。
アプリのコントローラーがActionController::Base
に代わってApplicationController
を継承するように、アプリのすべてのモデルがApplicationRecord
をスーパークラスとして使うようになりました。この変更により、アプリ全体のモデルの動作を1か所で変更できるようになりました。
Rails 4.2 を Rails 5.0 にアップグレードする場合、app/models/
ディレクトリにapplication_record.rb
ファイルを追加し、このファイルに以下の設定を追加する必要があります。
class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end
最後に、すべてのモデルが ApplicationRecord
を継承するように変更および確認してください。
3.3 throw(:abort)
でコールバックチェーンを停止する
Rails 4.2 では、Active RecordやActive Modelで'before'コールバックがfalse
を返すと、すべてのコールバックチェーンが停止する仕様でした。この場合、以後'before'コールバックは実行されず、コールバック内にラップされているアクションも実行されません。
Rails 5.0 ではこの副作用が修正され、Active RecordやActive Modelのコールバックでfalse
が返ってもコールバックチェーンが停止しなくなりました。その代わり、今後コールバックチェーンはthrow(:abort)
で明示的に停止する必要があります。
Rails 4.2 を Rails 5.0 にアップグレードした場合、こうしたコールバックでfalse
が返ったときに従来同様コールバックチェーンは停止しますが、この変更にともなう非推奨警告が表示されます。
この変更内容とその影響を十分理解しているのであれば、config/application.rb
に以下の記述を追加して非推奨警告をオフにできます。
ActiveSupport.halt_callback_chains_on_return_false = false
Active Support のコールバックはこのオプションの影響を受けないことにご注意ください。Active Supportのチェーンはどのような値が返っても停止しません。
詳細については#17227を参照してください。
3.4 ActiveJob は今後デフォルトで ApplicationJob を継承する
Rails 4.2 のActive JobはActiveJob::Base
を継承しますが、Rails 5.0 ではデフォルトでApplicationJob
を継承するよう変更されました。
Rails 4.2 を Rails 5.0 にアップグレードする場合、app/jobs/
ディレクトリにapplication_job.rb
ファイルを追加し、このファイルに以下の設定を追加する必要があります。
class ApplicationJob < ActiveJob::Base end
これにより、すべてのjobクラスがActiveJob::Baseを継承するようになります。
詳細については#19034を参照してください。
3.5 Rails コントローラのテスト
3.5.1 いくつかのヘルパーメソッドを rails-controller-testing
に抽出
assigns
メソッドとassert_template
メソッドはrails-controller-testing
gemに移転しました。これらのメソッドを引き続きコントローラのテストで使いたい場合は、Gemfileにgem 'rails-controller-testing'
を追加してください。
テストでRspecを使っている場合は、このgemのドキュメントで必須となっている追加の設定方法もご確認ください。
3.5.2 ファイルアップロード時の新しい振る舞い
ファイルアップロードのテストでActionDispatch::Http::UploadedFile
クラスを使用している場合、Rack::Test::UploadedFile
クラスに変更する必要があります。
詳細については#26404を参照してください。
3.6 production 環境での起動後は自動読み込みが無効になる
今後Railsがproduction環境で起動されると、自動読み込みがデフォルトで無効になります。
アプリケーションの一括読み込み(eager loading)は起動プロセスに含まれています。このため、トップレベルの定数についてはファイルをrequireしなくても問題なく利用でき、従来と同様に自動読み込みされます。
トップレベルより下で、実行時にのみ有効にする定数(通常のメソッド本体など)を定義した場合も、起動時に一括読み込みされるので問題なく利用できます。
ほとんどのアプリケーションでは、この変更に関して特別な対応は不要です。めったにないと思われますが、productionモードで動作するアプリケーションで自動読み込みが必要な場合は、Rails.application.config.enable_dependency_loading
をtrueに設定してください。
3.7 XML シリアライズ
RailsのActiveModel::Serializers::Xml
はactivemodel-serializers-xml
gemに移転しました。アプリケーションで今後もXMLシリアライズを使うには、Gemfileに「gem 'activemodel-serializers-xml'
」を追加してください。
3.8 古い mysql
データベース アダプタのサポートを終了
Rails 5で古いmysql
データベース アダプタのサポートが終了しました。原則としてmysql2
をお使いください。今後古いアダプタのメンテナンス担当者が決まった場合、アダプタは別のgemに切り出されます。
3.9 デバッガのサポートを終了
Rails 5が必要とするRuby 2.2では、debugger
はサポートされていません。代わりに、今後はbyebug
をお使いください。
3.10 タスクやテストの実行には bin/rails を使うこと
Rails 5 では、rakeに代わってbin/rails
でタスクやテストを実行できるようになりました。原則として、多くのタスクやテストはrakeでも引き続き実行できますが、一部のタスクやテストは完全にbin/railsに移行しました。
今後テストの実行には「bin/rails test
」をお使いください。
「rake dev:cache
」は「rails dev:cache
」に変更されました。
「bin/rails
」を実行すると、利用可能なコマンドリストを表示できます。
3.11 ActionController::Parameters
は今後 HashWithIndifferentAccess
を継承しない
アプリケーションで params
を呼び出すと、今後はハッシュではなくオブジェクトが返ります。現在使っているパラメーターがRailsで既に利用できている場合、変更は不要です。permitted?
の状態にかかわらずハッシュを読み取れることが前提のメソッド(slice
メソッドなど)にコードが依存している場合、まずアプリケーションをアップグレードしてpermitを指定し、続いてハッシュに変換する必要があります。
params.permit([:proceed_to, :return_to]).to_h
3.12 protect_from_forgery
は今後デフォルトで prepend: false
に設定される
protect_from_forgery
は今後デフォルトで prepend: false
に設定されます。これにより、protect_from_forgeryはアプリケーションで呼び出される時点でコールバックチェーンに挿入されます。protect_from_forgery
を常に最初に実行したい場合は、アプリケーションの設定でprotect_from_forgery prepend: true
を指定する必要があります。
3.13 デフォルトのテンプレート ハンドラは今後 RAW になる
拡張子がテンプレートハンドラになっていないファイルは、今後rawハンドラで出力されるようになります。従来のRailsでは、このような場合にはERBテンプレートハンドラで出力されました。
ファイルをrawハンドラで出力したくない場合は、ファイルに明示的に拡張子を与え、適切なテンプレート ハンドラで処理されるようにしてください。
3.14 テンプレート依存関係の指定でワイルドカードマッチングが追加された
テンプレート依存関係をワイルドカードマッチングで指定できるようになりました。以下のテンプレートを例に説明します。
<% # Template Dependency: recordings/threads/events/subscribers_changed %> <% # Template Dependency: recordings/threads/events/completed %> <% # Template Dependency: recordings/threads/events/uncompleted %>
上のようなテンプレートは、以下のようにワイルドカードを使えば1行で設定できます。
<% # Template Dependency: recordings/threads/events/* %>
3.15 ActionView::Helpers::RecordTagHelper
は、外部のgemに移動(record_tag_helper
)
content_tag_for
と div_for
が削除され、 content_tag
のみの利用が推奨されます。これらの古いメソッドを使い続けたい場合、 record_tag_helper
gemをGemfileに追加してください。
gem 'record_tag_helper', '~> 1.0'
詳細については#18411を参照してください。
3.16 protected_attributes
gem のサポートを終了
protected_attributes
gemのサポートは Rails 5 で終了しました。
3.17 activerecord-deprecated_finders
gem のサポートを終了
activerecord-deprecated_finders
gemのサポートは Rails 5 で終了しました。
3.18 ActiveSupport::TestCase
でのテストは今後デフォルトでランダムに実行される
アプリケーションのテストのデフォルトの実行順序は、従来の:sorted
から:random
に変更されました。:sorted
に戻すには以下のオプションを指定します。
# config/environments/test.rb Rails.application.configure do config.active_support.test_order = :sorted end
3.19 ActionController::Live
は Concern
に変更された
コントローラにincludeされている別のモジュールにActionController::Live
がincludeされている場合、ActiveSupport::Concern
をextendするコードの追加も必要です。または、StreamingSupport
がincludeされてから、self.included
フックを使ってActionController::Live
をコントローラに直接includeすることもできます。
理由: アプリケーションで独自のストリーミングモジュールを使用している場合、以下のコードはproductionモードで正常に動作しなくなる可能性があります。
# Warden/Devise で認証するストリーミングコントローラでの回避方法を示すコード # https://github.com/plataformatec/devise/issues/2332 を参照 # 上のissueではルーター内での認証で解決する方法もアドバイスされている class StreamingSupport include ActionController::Live # Rails 5 の production モードではこの行は動作しない # extend ActiveSupport::Concern # この行をコメント解除することで上の行が動作するようになる def process(name) super(name) rescue ArgumentError => e if e.message == 'uncaught throw :warden' throw :warden else raise e end end end
3.20 フレームワークの新しいデフォルト設定
3.20.1 Active Recordのbelongs_to
はデフォルトオプションで必須
関連付けが存在しない場合、belongs_to
でバリデーションエラーが発生するようになりました。
なお、この機能は関連付けごとにoptional: true
を指定してオフにできます。
新しいアプリケーションでは、このデフォルト設定が自動で有効になります。この設定を既存のアプリケーションに追加するには、イニシャライザでこの機能をオンにする必要があります
config.active_record.belongs_to_required_by_default = true
3.20.2 フォームごとのCSRFトークン
Rails 5 では、JavaScriptで作成されたフォームによるコードインジェクション攻撃に対応するため、フォーム単位でのCSRFトークンをサポートします。このオプションがオンの場合、アクションやメソッドで指定したCSRFトークンがアプリケーションのフォームごとに個別に生成されるようになります。
config.action_controller.per_form_csrf_tokens = true
3.20.3 OriginチェックによるCSRF対策
アプリケーションで、CSRF防御の一環としてHTTP Origin
ヘッダによるサイトの出自チェックを設定できるようになりました。以下の設定をtrueにすることで有効になります。
config.action_controller.forgery_protection_origin_check = true
3.20.4 Action Mailerのキュー名がカスタマイズ可能に
デフォルトのメイラー キュー名はmailers
です。新しい設定オプションを使うと、キュー名をグローバルに変更できます。以下の方法で設定します。
config.action_mailer.deliver_later_queue_name = :new_queue_name
3.20.5 Action Mailer のビューでフラグメントキャッシュをサポート
設定ファイルの config.action_mailer.perform_caching
で、Action Mailerのビューでキャッシュをサポートするかどうかを指定できます。
config.action_mailer.perform_caching = true
3.20.6 db:structure:dump
の出力形式のカスタマイズ
schema_search_path
や、その他のPostgreSQLエクステンションを使っている場合、スキーマのダンプ方法を指定できます。以下のように:all
を指定するとすべてのダンプが生成され、:schema_search_path
を指定するとスキーマ検索パスからダンプが生成されます。
config.active_record.dump_schemas = :all
3.20.7 サブドメインでのHSTSを有効にするSSLオプション
サブドメインで HSTS(HTTP Strict Transport Security)を有効にするには、以下の設定を使います。
config.ssl_options = { hsts: { subdomains: true } }
3.20.8 レシーバのタイムゾーンを保存する
Ruby 2.4を利用している場合、to_time
の呼び出しでレシーバのタイムゾーンを保存できます。
ActiveSupport.to_time_preserves_timezone = false
4 Rails 4.1からRails 4.2へのアップグレード
4.1 Web Console gem
最初に、Gemfile
のdevelopment
グループにgem 'web-console', '~> 2.0'
を追加し、bundle install
を実行してください (このgemはRailsを過去のバージョンからアップグレードした場合には含まれないので、手動で追加する必要があります)。gemのインストール完了後、<%= console %>
などのコンソールヘルパーへの参照をビューに追加するだけで、どのビューでもコンソールを利用できるようになります。このコンソールは、development環境のビューで表示されるすべてのエラーページにも表示されます。
4.2 Responders gem
respond_with
およびクラスレベルのrespond_to
メソッドは、responders
gemに移転しました。これらのメソッドを使用したい場合は、Gemfileにgem 'responders', '~> 2.0'
と記述するだけで利用できます。今後、respond_with
呼び出し、およびクラスレベルのrespond_to
呼び出しは、responders
gemなしでは動作しません。
# app/controllers/users_controller.rb class UsersController < ApplicationController respond_to :html, :json def show @user = User.find(params[:id]) respond_with @user end end
インスタンスレベルのrespond_to
は今回のアップグレードの影響を受けませんので、gemを追加する必要はありません。
# app/controllers/users_controller.rb class UsersController < ApplicationController def show @user = User.find(params[:id]) respond_to do |format| format.html format.json { render json: @user } end end end
詳細については#16526を参照してください。
4.3 トランザクションコールバックのエラー処理
現在のActive Recordでは、after_rollback
やafter_commit
コールバックでの例外を抑制しており、例外時にはログ出力のみが行われます。次のバージョンからは、これらのエラーは抑制されなくなりますのでご注意ください。今後は他のActive Recordコールバックと同様のエラー処理を行います。
after_rollback
コールバックやafter_commit
コールバックを定義すると、この変更にともなう非推奨警告が表示されるようになりました。この変更内容を十分理解し、受け入れる準備ができているのであれば、config/application.rb
に以下の記述を行なうことで非推奨警告が表示されないようにすることができます。
config.active_record.raise_in_transactional_callbacks = true
詳細については、#14488および#16537を参照してください。
4.4 テストケースの実行順序
Rails 5.0のテストケースは、デフォルトでランダムに実行されるようになる予定です。この変更に備えて、テスト実行順を明示的に指定するactive_support.test_order
という新しい設定オプションがRails 4.2に導入されました。このオプションを使用すると、たとえばテスト実行順を現行の仕様のままにしておきたい場合は:sorted
を指定したり、ランダム実行を今のうちに導入したい場合は:random
を指定したりすることができます。
このオプションに値が指定されていないと、非推奨警告が表示されます。非推奨警告が表示されないようにするには、test環境に以下の記述を追加します。
# config/environments/test.rb Rails.application.configure do config.active_support.test_order = :sorted # `:random`にしてもよい end
4.5 シリアル化属性
serialize :metadata, JSON
などのカスタムコーダーを使用している場合に、シリアル化属性 (serialized attribute) にnil
を割り当てると、コーダー内でnil
値を渡すのではなく、データベースにNULL
として保存されるようになりました (JSON
コーダーを使用している場合の"null"
など)。
4.6 Productionログのレベル
Rails 5のproduction環境では、デフォルトのログレベルが:info
から:debug
に変更される予定です。現在のログレベルを変更したくない場合はproduction.rb
に以下の行を追加してください。
# `:info`を指定すると現在のデフォルト設定が使用され、 # `:debug`を指定すると今後のデフォルト設定が使用される config.log_level = :info
4.7 Railsテンプレートのafter_bundle
Railsテンプレートを使用し、かつすべてのファイルを (Gitなどで) バージョン管理している場合、生成されたbinstubをバージョン管理システムに追加できません。これは、binstubの生成がBundlerの実行前に行われるためです。
# template.rb generate(:scaffold, "person name:string") route "root to: 'people#index'" $ rake db:migrate git :init git add: "." git commit: %Q{ -m 'Initial commit' }
この問題を回避するために、git
呼び出しをafter_bundle
ブロック内に置くことができるようになりました。こうすることで、binstubの生成が終わってからBundlerが実行されます。
# template.rb generate(:scaffold, "person name:string") route "root to: 'people#index'" rake("db:migrate") after_bundle do git :init git add: "." git commit: %Q{ -m 'Initial commit' } end
4.8 RailsのHTMLサニタイザ
アプリケーションでHTMLの断片をサニタイズする方法に新しい選択肢が1つ増えました。従来の伝統的なHTMLスキャンによるサニタイズは公式に非推奨化されました。現在推奨される方法はRails HTMLサニタイザ
です。
これにより、sanitize
、sanitize_css
、strip_tags
、およびstrip_links
メソッドは新しい実装に基いて動作するようになります。
新しいサニタイザは、内部でLoofahを使用しています。そしてLoofahはNokogiriを使用しています。Nokogiriで使用されているXMLパーサーはCとJavaの両方で記述されているので、使用しているRubyのバージョンにかかわらずサニタイズが高速化されるようになりました。
新しいRailsではsanitize
メソッドが更新され、Loofah::Scrubber
を使用して強力なスクラブを行なうことができます。スクラブの使用例はここを参照。
PermitScrubber
およびTargetScrubber
という2つのスクラバーが新たに追加されました。詳細については、gemのReadmeを参照してください。
PermitScrubber
およびTargetScrubber
のドキュメントには、どの要素をどのタイミングで除去すべきかを完全に制御する方法が記載されています。
従来のままのサニタイザの実装が必要な場合は、アプリケーションのGemfileにrails-deprecated_sanitizer
を追加してください。
gem 'rails-deprecated_sanitizer'
4.9 RailsのDOMのテスト
assert_tag
などを含むTagAssertions
モジュールは非推奨になりました。今後推奨されるのは、ActionViewからrails-dom-testing gemに移行したSelectorAssertions
モジュールのassert_select
メソッドです。
4.10 マスク済み真正性トークン
SSL攻撃を緩和するために、form_authenticity_token
がマスクされるようになりました。これにより、このトークンはリクエストごとに変更されます。トークンの検証はマスク解除 (unmasking)とそれに続く復号化 (decrypting) によって行われます。この変更が行われたことにより、railsアプリケーション以外のフォームから送信される、静的なセッションCSRFトークンに依存するリクエストを検証する際には、このマスク済み真正性トークンのことを常に考慮する必要がありますのでご注意ください。
4.11 Action Mailer
従来は、メイラークラスでメイラーメソッドを呼び出すと、該当するインスタンスメソッドが直接実行されました。Active Jobと#deliver_later
メソッドの導入に伴い、この動作が変更されました。Rails 4.2では、これらのインスタンスメソッド呼び出しはdeliver_now
またはdeliver_later
が呼び出されるまで実行延期されます。以下に例を示します。
class Notifier < ActionMailer::Base def notify(user, ...) puts "Called" mail(to: user.email, ...) end end mail = Notifier.notify(user, ...) # Notifier#notifyはこの時点では呼び出されない mail = mail.deliver_now # "Called"を出力する
この変更によって実行結果が大きく異なるアプリケーションはそれほどないと思われます。ただし、メイラー以外のメソッドを同期的に実行したい場合、かつ従来の同期的プロキシ動作に依存している場合は、これらのメソッドをメイラークラスにクラスメソッドとして直接定義する必要があります。
class Notifier < ActionMailer::Base def self.broadcast_notifications(users, ...) users.each { |user| Notifier.notify(user, ...) } end end
4.12 外部キーのサポート
移行DSLが拡張され、外部キー定義をサポートするようになりました。Foreigner gemを使っていた場合は、この機会に削除するとよいでしょう。Railsの外部キーサポートは、Foreignerの全機能ではなく、一部のみである点にご注意ください。このため、Foreignerの定義を必ずしもRailsの移行DSLに置き換えられないことがあります。
移行手順は次のとおりです。
- Gemfileから
gem "foreigner"
を削除します。 -
bundle install
を実行します。 -
bin/rake db:schema:dump
を実行します。 - 外部キー定義と必要なオプションが
db/schema.rb
にすべて含まれていることを確認します。
5 Rails 4.0からRails 4.1へのアップグレード
5.1 リモート <script>
タグにCSRF保護を実施
これを行わないと、「なぜかテストがとおらない...orz」「<script>
ウィジェットがおかしい!」などという結果になりかねません。
JavaScriptレスポンスを伴うGETリクエストもクロスサイトリクエストフォージェリ (CSRF) 保護の対象となりました。これは、サイトの<script>
タグのJavaScriptが第三者のサイトから参照されて重要なデータが奪取されないよう保護するためのものです。
つまり、以下を使用する機能テストと結合テストは
get :index, format: :js
CSRF保護をトリガーするようになります。以下のように書き換え、
xhr :get, :index, format: :js
XmlHttpRequest
を明示的にテストしてください。
自サイトの<script>
はクロス参照の出発点として扱われるため、同様にブロックされます。JavaScriptを本当に<script>
タグから読み込む場合は、そのアクションでCSRF保護を明示的にスキップしてください。
5.2 Spring
アプリケーションのプリローダーとしてSpringを使用する場合は、以下を行う必要があります。
-
gem 'spring', group: :development
をGemfile
に追加する -
bundle install
を実行してSpringをインストールする -
bundle exec spring binstub --all
を実行してbinstubをSpring化する
ユーザーが定義したRakeタスクはデフォルトでdevelopment環境で動作するようになります。これらのRakeタスクを他の環境でも実行したい場合はSpring READMEを参考にしてください。
5.3 config/secrets.yml
新しいsecrets.yml
に秘密鍵を保存したい場合は以下の手順を実行します。
-
secrets.yml
ファイルをconfig
フォルダ内に作成し、以下の内容を追加します。development: secret_key_base: test: secret_key_base: production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
secret_token.rb
イニシャライザに記載されている既存のsecret_key_base
の秘密キーを取り出してSECRET_KEY_BASE環境変数に設定し、Railsアプリケーションをproductionモードで実行するすべてのユーザーが秘密キーの恩恵を受けられるようにします。あるいは、既存のsecret_key_base
をsecret_token.rb
イニシャライザからsecrets.yml
のproductionセクションにコピーし、'<%= ENV["SECRET_KEY_BASE"] %>'を置き換えることもできます。secret_token.rb
イニシャライザを削除しますrake secret
を実行し、development
セクションtest
セクションに新しい鍵を生成します。サーバーを再起動します。
5.4 テストヘルパーの変更
テストヘルパーに含まれているActiveRecord::Migration.check_pending!
呼び出しは削除できます。このチェックはrequire 'rails/test_help'
の際に自動的に行われるようになりました。この呼び出しを削除しなくても悪影響が生じることはありません。
5.5 Cookiesシリアライザ
Rails 4.1より前に作成されたアプリケーションでは、Marshal
を使用してcookie値を署名済みまたは暗号化したcookies jarにシリアライズしていました。アプリケーションで新しいJSON
ベースのフォーマットを使用したい場合、以下のような内容を持つイニシャライザファイルを追加できます。
Rails.application.config.action_dispatch.cookies_serializer = :hybrid
これにより、Marshal
でシリアライズされた既存のcookiesを、新しいJSON
ベースのフォーマットに透過的に移行できます。
:json
または:hybrid
シリアライザを使用する場合、一部のRubyオブジェクトがJSONとしてシリアライズされない可能性があることにご注意ください。たとえば、Date
オブジェクトやTime
オブジェクトはstringsとしてシリアライズされ、Hash
のキーはstringに変換されます。
class CookiesController < ApplicationController def set_cookie cookies.encrypted[:expiration_date] = Date.tomorrow # => Thu, 20 Mar 2014 redirect_to action: 'read_cookie' end def read_cookie cookies.encrypted[:expiration_date] # => "2014-03-20" end end
cookieには文字列や数字などの単純なデータだけを保存することをお勧めします。cookiesに複雑なオブジェクトを保存しなければならない場合は、後続のリクエストでcookiesから値を読み出す場合の変換については自分で面倒を見る必要があります。
cookieセッションストアを使用する場合、session
やflash
ハッシュについてもこのことは該当します。
5.6 Flash構造の変更
Flashメッセージのキーが文字列に正規化 されました。シンボルまたは文字列のどちらでもアクセスできます。Flashのキーを取り出すと常に文字列になります。
flash["string"] = "a string" flash[:symbol] = "a symbol" # Rails < 4.1 flash.keys # => ["string", :symbol] # Rails >= 4.1 flash.keys # => ["string", "symbol"]
Flashメッセージのキーは文字列と比較してください。
5.7 JSONの扱いの変更点
Rails 4.1ではJSONの扱いが大きく変更された点が4つあります。
5.7.1 MultiJSONの廃止
MultiJSONはその役目を終えて end-of-life Railsから削除されました。
アプリケーションがMultiJSONに直接依存している場合、以下のような対応方法があります。
'multi_json'をGemfileに追加する。ただしこのGemは将来使えなくなるかもしれません。
obj.to_json
とJSON.parse(str)
を使用してMultiJSONから乗り換える。
MultiJson.dump
と MultiJson.load
をそれぞれJSON.dump
とJSON.load
に単純に置き換えては「いけません」。これらのJSON gem APIは任意のRubyオブジェクトをシリアライズおよびデシリアライズするためのものであり、一般に安全ではありません。
5.7.2 JSON gemの互換性
これまでのRailsでは、JSON gemとの互換性に何らかの問題が生じていました。Railsアプリケーション内のJSON.generate
とJSON.dump
ではときたまエラーが生じることがありました。
Rails 4.1では、Rails自身のエンコーダをJSON gemから切り離すことでこれらの問題が修正されました。JSON gem APIは今後正常に動作しますが、その代わりJSON gem APIからRails特有の機能にアクセスすることはできなくなります。以下に例を示します。
class FooBar def as_json(options = nil) { foo: 'bar' } end end >> FooBar.new.to_json # => "{\"foo\":\"bar\"}" >> JSON.generate(FooBar.new, quirks_mode: true) # => "\"#<FooBar:0x007fa80a481610>\""
5.7.3 新しいJSONエンコーダ
Rails 4.1のJSONエンコーダは、JSON gemを使用するように書き直されました。この変更によるアプリケーションへの影響はほとんどありません。ただし、エンコーダが書き直された際に以下の機能がエンコーダから削除されました。
- データ構造の循環検出
-
encode_json
フックのサポート -
BigDecimal
オブジェクトを文字ではなく数字としてエンコードするオプション
アプリケーションがこれらの機能に依存している場合は、activesupport-json_encoder
gemをGemfileに追加することで以前の状態に戻すことができます。
5.7.4 TimeオブジェクトのJSON形式表現
日時に関連するコンポーネント(Time
、DateTime
、ActiveSupport::TimeWithZone
)を持つオブジェクトに対して#as_json
を実行すると、デフォルトでミリ秒単位の精度で値が返されるようになりました。ミリ秒より精度の低い従来方式にしておきたい場合は、イニシャライザに以下を設定してください。
ActiveSupport::JSON::Encoding.time_precision = 0
5.8 インラインコールバックブロックでreturn
の使用法
以前のRailsでは、インラインコールバックブロックで以下のようにreturn
を使用することが許容されていました。
class ReadOnlyModel < ActiveRecord::Base before_save { return false } # 良くない end
この動作は決して意図されたものではありません。ActiveSupport::Callbacks
が書き直され、上のような動作はRails 4.1では許容されなくなりました。インラインコールバックブロックでreturn
文を書くと、コールバック実行時にLocalJumpError
が発生するようになりました。
インラインコールバックブロックでreturn
を使用している場合、以下のようにリファクタリングすることで、返された値として評価されるようになります。
class ReadOnlyModel < ActiveRecord::Base before_save { false } # 良い end
return
を使用したいのであれば、明示的にメソッドを定義することが推奨されます。
class ReadOnlyModel < ActiveRecord::Base before_save :before_save_callback # 良い private def before_save_callback return false end end
この変更は、Railsでコールバックを使用している多くの箇所に適用されます。これにはActive RecordとActive ModelのコールバックやAction Controllerのフィルタ(before_action
など)も含まれます。
詳細についてはこのpull requestを参照してください。
5.9 Active Recordフィクスチャで定義されたメソッド
Rails 4.1では、各フィクスチャのERBは独立したコンテキストで評価されます。このため、あるフィクスチャで定義されたヘルパーメソッドは他のフィクスチャでは利用できません。
ヘルパーメソッドを複数のフィクスチャで使用するには、4.1で新しく導入されたActiveRecord::FixtureSet.context_class
(test_helper.rb
) に含まれるモジュールで定義する必要があります。
module FixtureFileHelpers def file_sha(path) Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path))) end end ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
5.10 I18nオプションでavailable_localesリストの使用が強制される
Rails 4.1からI18nオプションenforce_available_locales
がデフォルトでtrue
になりました。この設定にすると、I18nに渡されるすべてのロケールは、available_localesリストで宣言されていなければ使用できません。
この機能をオフにしてI18nですべての種類のロケールオプションを使用できるようにするには、以下のように変更します。
config.i18n.enforce_available_locales = false
available_localesの強制はセキュリティのために行われていることにご注意ください。つまり、アプリケーションが把握していないロケールを持つユーザー入力が、ロケール情報として使用されることのないようにするためのものです。従って、やむを得ない理由がない限りこのオプションはfalseにしないでください。
5.11 リレーションに対する破壊的メソッド呼び出し
Relation
には#map!
や#delete_if
などの破壊的メソッド (mutator method) が含まれなくなりました。これらのメソッドを使用したい場合は#to_a
を呼び出してArray
に変更してからにしてください。
この変更は、Relation
に対して破壊的メソッドを直接呼び出すことによる奇妙なバグや混乱を防止するために行われました。
# 以前の破壊的な呼び出し方法 Author.where(name: 'Hank Moody').compact! # 今後の破壊的な呼び出し方法 authors = Author.where(name: 'Hank Moody').to_a authors.compact!
5.12 デフォルトスコープの変更
デフォルトのスコープは、条件を連鎖した場合にオーバーライドされなくなりました。
以前のバージョンでは、モデルでdefault_scope
を定義すると、同じフィールドで連鎖した条件によってオーバーライドされました。現在は、他のスコープと同様、マージされるようになりました。
変更前:
class User < ActiveRecord::Base default_scope { where state: 'pending' } scope :active, -> { where state: 'active' } scope :inactive, -> { where state: 'inactive' } end User.all # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' User.active # SELECT "users".* FROM "users" WHERE "users"."state" = 'active' User.where(state: 'inactive') # SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
変更後:
class User < ActiveRecord::Base default_scope { where state: 'pending' } scope :active, -> { where state: 'active' } scope :inactive, -> { where state: 'inactive' } end User.all # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' User.active # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'active' User.where(state: 'inactive') # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' AND "users"."state" = 'inactive'
以前と同じ動作に戻したい場合は、unscoped
、unscope
、rewhere
、またはexcept
を使用してdefault_scope
の条件を明示的に除外する必要があります。
class User < ActiveRecord::Base default_scope { where state: 'pending' } scope :active, -> { unscope(where: :state).where(state: 'active') } scope :inactive, -> { rewhere state: 'inactive' } end User.all # SELECT "users".* FROM "users" WHERE "users"."state" = 'pending' User.active # SELECT "users".* FROM "users" WHERE "users"."state" = 'active' User.inactive # SELECT "users".* FROM "users" WHERE "users"."state" = 'inactive'
5.13 文字列からのコンテンツ描出
Rails 4.1のrender
に:plain
、:html
、:body
オプションが導入されました。以下のようにコンテンツタイプを指定できるため、文字列ベースのコンテンツ表示にはこれらのオプションの使用が推奨されます。
-
render :plain
を実行するとcontent typeはtext/plain
に設定される -
render :html
を実行するとcontent typeはtext/html
に設定される -
render :body
を実行した場合、content typeヘッダーは「設定されない」
セキュリティ上の観点から、レスポンスのbodyにマークアップを含めない場合にはrender :plain
を使用すべきです。これによって多くのブラウザが安全でないコンテンツをエスケープできるからです。
今後のバージョンでは、render :text
は非推奨にされる予定です。今のうちに、正しい:plain
、:html
、:body
オプションに切り替えてください。render :text
を使用するとtext/html
で送信されるため、セキュリティ上のリスクが生じる可能性があります。
5.14 PostgreSQLのデータ型'json'と'hstore'について
Rails 4.1では、PostgreSQLのjson
カラムとhstore
カラムを、文字列をキーとするRubyのHash
に対応付けるようになりました。なお、以前のバージョンではHashWithIndifferentAccess
が使用されていました。この変更は、Rails 4.1以降ではシンボルを使用してこれらのデータ型にアクセスできなくなるということを意味します。store_accessors
メソッドはjson
カラムやhstore
カラムに依存しているので、同様にシンボルでのアクセスが行えなくなります。今後は常に文字列をキーにするようにしてください。
5.15 ActiveSupport::Callbacks
では明示的にブロックを使用すること
Rails 4.1からはActiveSupport::Callbacks.set_callback
の呼び出しの際に明示的にブロックを渡すことが期待されます。これは、ActiveSupport::Callbacks
がRails 4.1リリースにあたって大幅に書き換えられたことによるものです。
# Rails 4.0の場合 set_callback :save, :around, ->(r, &block) { stuff; result = block.call; stuff } # Rails 4.1の場合 set_callback :save, :around, ->(r, block) { stuff; result = block.call; stuff }
6 Rails 3.2からRails 4.0へのアップグレード
Railsアプリケーションのバージョンが3.2より前の場合、まず3.2へのアップグレードを完了してからRails 4.0へのアップグレードを開始してください。
以下の変更は、アプリケーションをRails 4.0にアップグレードするためのものです。
6.1 HTTP PATCH
Rails 4では、config/routes.rb
でRESTfulなリソースが宣言されたときに、更新用の主要なHTTP verbとしてPATCH
が使用されるようになりました。update
アクションは従来通り使用でき、PUT
リクエストは今後もupdate
アクションにルーティングされます。標準的なRESTfulのみを使用しているのであれば、これに関する変更は不要です。
resources :users
<%= form_for @user do |f| %>
class UsersController < ApplicationController def update # 変更不要:PATCHが望ましいがPUTも使用できる end end
ただし、form_for
を使用してリソースを更新しており、PUT
HTTPメソッドを使用するカスタムルーティングと連動しているのであれば、変更が必要です。
resources :users, do put :update_name, on: :member end
<%= form_for [ :update_name, @user ] do |f| %>
class UsersController < ApplicationController def update_name # 変更が必要: form_forは、存在しないPATCHルートを探そうとする end end
このアクションがパブリックなAPIで使用されておらず、HTTPメソッドを自由に変更できるのであれば、ルーティングを更新してpatch
をput
の代りに使用できます。
Rails 4でPUT
リクエストを/users/:id
に送信すると、従来と同様update
にルーティングされます。このため、実際のPUTリクエストを受け取るAPIは今後も利用できます。この場合、PATCH
リクエストも/users/:id
経由でupdate
アクションにルーティングされます。
resources :users do patch :update_name, on: :member end
このアクションがパブリックなAPIで使用されており、HTTPメソッドを自由に変更できないのであれば、フォームを更新してPUT
を代りに使用できます。
<%= form_for [ :update_name, @user ], method: :put do |f| %>
PATCHおよびこの変更が行われた理由についてはRailsブログの この記事 を参照してください。
6.1.1 メディアタイプに関するメモ
PATCH
verbに関する追加情報 PATCH
では異なるメディアタイプを使用する必要がある。JSON Patch などが該当します。RailsはJSON Patchをネイティブではサポートしませんが、サポートは簡単に追加できます。
# コントローラに以下を書く def update respond_to do |format| format.json do # 部分的な変更を行なう @article.update params[:article] end format.json_patch do # 何か気の利いた変更を行なう end end end # config/initializers/json_patch.rb に以下を書く Mime::Type.register 'application/json-patch+json', :json_patch
JSON Patchは最近RFC化されたばかりなのでRubyライブラリはそれほどありません。Aaron Pattersonの hana gemが代表的ですが、最新の仕様変更をすべてサポートしているわけではありません。
6.2 Gemfile
Rails 4.0ではassets
グループがGemfileから削除されました。アップグレード時にはこの記述をGemfile
から削除する必要があります。アプリケーションのconfig/application.rb
ファイルも以下のように更新する必要があります。
# Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups)
6.3 vendor/plugins
Rails 4.0 では vendor/plugins
読み込みのサポートは完全に終了しました。使用するプラグインはすべてgemに展開してGemfileに追加しなければなりません。 理由があってプラグインをgemにしないのであれば、プラグインをlib/my_plugin/*
に移動し、適切な初期化の記述をconfig/initializers/my_plugin.rb
に書いてください。
6.4 Active Record
-
関連付けに関する若干の不整合 のため、Rails 4.0ではActive Recordからidentity mapが削除されました。この機能をアプリケーションで手動で有効にしたい場合は、今や無効になった
config.active_record.identity_map
を削除する必要があるでしょう。
コレクション関連付けのdelete
メソッドは、integer
やString
引数をレコードの他にレコードIDとしても受け付けるようになりました。これによりdestroy
メソッドの動作にかなり近くなりました。以前はこのような引数を使用するとActiveRecord::AssociationTypeMismatch
例外が発生しました。Rails 4.0からは、delete
メソッドを使用すると、与えられたIDにマッチするレコードを自動的に探すようになりました。
Rails 4.0では、カラムやテーブルの名前を変更すると、関連するインデックスも自動的にリネームされるようになりました。インデックス名を変更するためだけのマイグレーションは今後不要になりました。
Rails 4.0の
serialized_attributes
メソッドとattr_readonly
メソッドは、クラスメソッドとしてのみ使用するように変更されました。これらのメソッドをインスタンスメソッドとして使用することは非推奨となったため、行わないでください。たとえばself.serialized_attributes
はself.class.serialized_attributes
のようにクラスメソッドとして使用してください。デフォルトのコーダーを使用する場合、シリアル化属性に
nil
を渡すと、YAML全体にわたって (nil
値を渡す代わりに)NULL
としてデータベースに保存されます ("--- \n...\n"
)。Rails 4.0ではStrong Parametersの導入に伴い、
attr_accessible
とattr_protected
が廃止されました。これらを引き続き使用したい場合は、Protected Attributes gem を導入することでスムーズにアップグレードすることができます。Protected Attributesを使用していないのであれば、
whitelist_attributes
やmass_assignment_sanitizer
オプションなど、このgemに関連するすべてのオプションを削除できます。Rails 4.0のスコープでは、Procやlambdaなどの呼び出し可能なオブジェクトの使用が必須となりました。
scope :active, where(active: true) # 上のコードは以下のように変更する必要がある scope :active, -> { where active: true }
ActiveRecord::FixtureSet
の導入に伴い、Rails 4.0ではActiveRecord::Fixtures
が非推奨となりました。ActiveSupport::TestCase
の導入に伴い、Rails 4.0ではActiveRecord::TestCase
が非推奨となりました。Rails 4.0では、ハッシュを使用する旧来のfinder APIが非推奨となりました。これまでfinderオプションを受け付けていたメソッドは、これらのオプションを今後受け付けなくなります。たとえば、
Book.find(:all, conditions: { name: '1984' })
は非推奨です。今後はBook.where(name: '1984')
をご使用ください。-
動的なメソッドは、
find_by_...
とfind_by_...!
を除いて非推奨になりました。以下のように変更してください。-
find_all_by_...
に代えてwhere(...)
を使用 -
find_last_by_...
に代えてwhere(...).last
を使用 -
scoped_by_...
に代えてwhere(...)
を使用` -
find_or_initialize_by_...
に代えてfind_or_initialize_by(...)
を使用` -
find_or_create_by_...
に代えてfind_or_create_by(...)
を使用`
-
旧来のfinderが配列を返していたのに対し、
where(...)
はリレーションを返します。Array
が必要な場合は,where(...).to_a
を使用してください。これらの同等なメソッドが実行するSQLは、従来の実装と同じではありません。
旧来のfinderを再度有効にしたい場合は、activerecord-deprecated_finders gem を使用できます。
Rails 4.0 では、
has_and_belongs_to_many
リレーションで2番目のテーブル名の共通プレフィックスを除去する際に、デフォルトでjoin tableを使うよう変更されました。共通プレフィックスがあるモデル同士のhas_and_belongs_to_many
リレーションでは、必ずjoin_table
オプションを指定する必要があります。以下に例を示します。
CatalogCategory < ActiveRecord::Base has_and_belongs_to_many :catalog_products, join_table: 'catalog_categories_catalog_products' end CatalogProduct < ActiveRecord::Base has_and_belongs_to_many :catalog_categories, join_table: 'catalog_categories_catalog_products' end
- プレフィックスではスコープも同様に考慮されるので、
Catalog::Category
とCatalog::Product
間のリレーションや、Catalog::Category
とCatalogProduct
間のリレーションも同様に更新する必要があります。
6.5 Active Resource
Rails 4.0ではActive Resourceがgem化されました。この機能が必要な場合はActive Resource gem をGemfileに追加できます。
6.6 Active Model
Rails 4.0では
ActiveModel::Validations::ConfirmationValidator
にエラーがアタッチされる方法が変更されました。確認バリデーションが失敗したときに、attribute
ではなく:#{attribute}_confirmation
にアタッチされるようになりました。Rails 4.0の
ActiveModel::Serializers::JSON.include_root_in_json
のデフォルト値がfalse
に変更されました。これにより、Active Model SerializersとActive Recordオブジェクトのデフォルトの動作が同じになりました。これにより、config/initializers/wrap_parameters.rb
ファイルの以下のオプションをコメントアウトしたり削除したりできるようになりました。
# Disable root element in JSON by default. # ActiveSupport.on_load(:active_record) do # self.include_root_in_json = false # end
6.7 Action Pack
- Rails 4.0から
ActiveSupport::KeyGenerator
が導入され、署名付きcookiesの生成と照合などに使用されるようになりました。Rails 3.xで生成された既存の署名付きcookiesは、既存のsecret_token
はそのままにしてsecret_key_base
を新しく追加することで透過的にアップグレードされます。
# config/initializers/secret_token.rb Myapp::Application.config.secret_token = 'existing secret token' Myapp::Application.config.secret_key_base = 'new secret key base'
注意:secret_key_base
を設定するのは、Rails 4.xへのユーザーベースの移行が100%完了し、Rails 3.xにロールバックする必要が完全になくなってからにしてください。これは、Rails 4.xの新しいsecret_key_base
を使用して署名されたcookiesにはRails 3.xのcookiesとの後方互換性がないためです。他のアップグレードが完全に完了するまでは、既存のsecret_token
をそのままにしてsecret_key_base
を設定せず、非推奨警告を無視するという選択肢もあります。
外部アプリケーションやJavaScriptからRailsアプリケーションの署名付きセッションcookies (または一般の署名付きcookies) を読み出せる必要がある場合は、これらの問題を切り離すまではsecret_key_base
を設定しないでください。
- Rails 4.0では、
secret_key_base
が設定されているとcookieベースのセッションの内容が暗号化されます。Rails 3.xではcookieベースのセッションへの署名は行われますが暗号化は行われません。署名付きcookiesは、そのRailsアプリケーションで生成されたことが確認でき、不正が防止されるという意味では安全です。しかしセッションの内容はエンドユーザーから見えてしまいます。内容を暗号化することで懸念を取り除くことができ、パフォーマンスの低下もそれほどありません。
セッションcookiesを暗号化する方法の詳細についてはPull Request #9978 を参照してください。
Rails 4.0 では
ActionController::Base.asset_path
オプションが廃止されました。代りにアセットパイプライン機能をご利用ください。Rails 4.0では
ActionController::Base.page_cache_extension
オプションが非推奨になりました。代りにActionController::Base.default_static_extension
をご利用ください。Rails 4.0のAction PackからActionとPageのキャッシュ機能が取り除かれました。コントローラで
caches_action
を使用したい場合はactionpack-action_caching
gemを、caches_page
を使用したい場合はactionpack-page_caching
gemをそれぞれGemfileに追加する必要があります。Rails 4.0からXMLパラメータパーサーが取り除かれました。この機能が必要な場合は
actionpack-xml_parser
gemを追加する必要があります。
Rails 4.0 では、シンボルやprocがnilを返す場合の、デフォルトの layout
ルックアップ設定が変更されました。動作を「no layout」にするには、nilではなくfalseを返すようにします。
Rails 4.0のデフォルトのmemcachedクライアントが
memcache-client
からdalli
に変更されました。アップグレードするには、単にgem 'dalli'
をGemfile
に追加します。Rails 4.0ではコントローラでの
dom_id
およびdom_class
メソッドの使用が非推奨になりました (ビューでの使用は問題ありません)。この機能が必要なコントローラではActionView::RecordIdentifier
モジュールをインクルードする必要があります。Rails 4.0では
link_to
ヘルパーでの:confirm
オプションが非推奨になりました。代わりにデータ属性を使用してください (例:data: { confirm: 'Are you sure?' }
)。link_to_if
やlink_to_unless
などでも同様の対応が必要です。Rails 4.0では
assert_generates
、assert_recognizes
、assert_routing
の動作が変更されました。これらのアサーションからはActionController::RoutingError
の代りにAssertion
が発生するようになりました。Rails 4.0では、名前付きルートの定義が重複している場合に
ArgumentError
が発生するようになりました。このエラーは、明示的に定義された名前付きルートやresources
メソッドによってトリガされます。名前付きルートexample_path
が衝突している例を2つ示します。
get 'one' => 'test#example', as: :example get 'two' => 'test#example', as: :example
resources :examples get 'clashing/:id' => 'test#example', as: :example
最初の例では、複数のルーティングで同じ名前を使用しないようにすれば回避できます。次の例では、only
またはexcept
オプションをresources
メソッドで使用することで、作成されるルーティングを制限することができます。詳細は Routing Guide を参照。
- Rails 4.0ではunicode文字のルーティングの描出方法が変更されました。unicode文字を使用するルーティングを直接描出できるようになりました。既にこのようなルーティングを使用している場合は、以下の変更が必要です。
get Rack::Utils.escape('こんにちは'), controller: 'welcome', action: 'index'
上のコードは以下のように変更する必要があります。
get 'こんにちは', controller: 'welcome', action: 'index'
- Rails 4.0でルーティングに
match
を使用する場合は、リクエストメソッドの指定が必須となりました。以下に例を示します。
# Rails 3.x match '/' => 'root#index' # 上のコードは以下のように変更する必要があります。 match '/' => 'root#index', via: :get # または get '/' => 'root#index'
- Rails 4.0から
ActionDispatch::BestStandardsSupport
ミドルウェアが削除されました。<!DOCTYPE html>
は既に https://msdn.microsoft.com/en-us/library/jj676915(v=vs.85).aspx の標準モードをトリガするようになり、ChromeFrameヘッダはconfig.action_dispatch.default_headers
に移動されました。
アプリケーションコード内にあるこのミドルウェアへの参照はすべて削除する必要がありますのでご注意ください。例:
# 例外発生 config.middleware.insert_before(Rack::Lock, ActionDispatch::BestStandardsSupport)
環境設定も確認し、config.action_dispatch.best_standards_support
がある場合は削除します。
Rails 4.0のアセットのプリコンパイルでは、
vendor/assets
およびlib/assets
にある非JS/CSSアセットを自動的にはコピーしなくなりました。Railsアプリケーションとエンジンの開発者は、これらのアセットを手動でapp/assets
に置き、config.assets.precompile
を設定してください。Rails 4.0では、リクエストされたフォーマットがアクションで扱えなかった場合に
ActionController::UnknownFormat
が発生するようになりました。デフォルトでは、この例外は406 Not Acceptable応答として扱われますが、この動作をオーバーライドすることができます。Rails 3では常に406 Not Acceptableが返されます。オーバーライドはできません。Rails 4.0では、
ParamsParser
がリクエストパラメータをパースできなかった場合に一般的なActionDispatch::ParamsParser::ParseError
例外が発生するようになりました。MultiJson::DecodeError
のような低レベルの例外の代りにこの例外をレスキューすることができます。Rails 4.0では、URLプレフィックスで指定されたアプリケーションにエンジンがマウントされている場合に
SCRIPT_NAME
が正しく入れ子になるようになりました。今後はURLプレフィックスの上書きを回避するためにdefault_url_options[:script_name]
を設定する必要はありません。Rails 4.0では
ActionDispatch::Integration
の導入に伴いActionController::Integration
が非推奨となりました。Rails 4.0では
ActionDispatch::IntegrationTest
の導入に伴いActionController::IntegrationTest
は非推奨となりました。Rails 4.0では
ActionDispatch::PerformanceTest
の導入に伴いActionController::PerformanceTest
が非推奨となりました。Rails 4.0では
ActionDispatch::Request
の導入に伴いActionController::AbstractRequest
が非推奨となりました。Rails 4.0では
ActionDispatch::Request
の導入に伴いActionController::Request
が非推奨となりました。Rails 4.0では
ActionDispatch::Response
の導入に伴いActionController::AbstractResponse
が非推奨となりました。Rails 4.0では
ActionDispatch::Response
の導入に伴いActionController::Response
が非推奨となりました。Rails 4.0では
ActionDispatch::Routing
の導入に伴いActionController::Routing
が非推奨となりました。
6.8 Active Support
Rails 4.0ではERB::Util#json_escape
のエイリアスj
が廃止されました。このエイリアスj
は既にActionView::Helpers::JavaScriptHelper#escape_javascript
で使用されているためです。
6.8.1 キャッシュ
Rails 3系とRails 4.0とで、キャッシュ用のメソッドが変更されましたキャッシュの名前空間を変更し、コールドキャッシュ (cold cache) を使って更新してください。
6.9 ヘルパーの読み込み順序
Rails 4.0では複数のディレクトリからのヘルパーの読み込み順が変更されました。以前はすべてのヘルパーをいったん集めてからアルファベット順にソートしていました。Rails 4.0にアップグレードすると、ヘルパーは読み込まれたディレクトリの順序を保持し、ソートは各ディレクトリ内でのみ行われます。helpers_path
パラメータを明示的に使用している場合を除いて、この変更はエンジンからヘルパーを読み込む方法にしか影響しません。ヘルパー読み込みの順序に依存している場合は、アップグレード後に正しいメソッドが使用できているかどうかを確認する必要があります。エンジンが読み込まれる順序を変更したい場合は、config.railties_order=
メソッドを使用できます。
6.10 Active Record ObserverとAction Controller Sweeper
Active Record Observer
とAction Controller Sweeper
はrails-observers
gemに切り出されました。これらの機能が必要な場合はrails-observers
gemを追加してください。
6.11 sprockets-rails
-
assets:precompile:primary
およびassets:precompile:all
は削除されました。assets:precompile
を代りに使用してください。 -
config.assets.compress
オプションは、たとえば以下のようにconfig.assets.js_compressor
に変更する必要があります。
config.assets.js_compressor = :uglifier
6.12 sass-rails
- 引数を2つ使用する
asset-url
は非推奨となりました。たとえば、asset-url("rails.png", image)
はasset-url("rails.png")
とする必要があります。
7 Rails 3.1からRails 3.2へのアップグレード
Railsアプリケーションのバージョンが3.1よりも古い場合、まず3.1へのアップグレードを完了してからRails 3.2へのアップグレードを開始してください。
以下の変更は、Rails 3.2.xにアップグレードするためのものです。
7.1 Gemfile
Gemfile
を以下のように変更します。
gem 'rails', '3.2.21' group :assets do gem 'sass-rails', '~> 3.2.6' gem 'coffee-rails', '~> 3.2.2' gem 'uglifier', '>= 1.0.3' end
7.2 config/environments/development.rb
development環境にいくつかの新しい設定を追加する必要があります。
# Active Recordのモデルをマスアサインメントから保護するために例外を発生する config.active_record.mass_assignment_sanitizer = :strict # クエリの実行計画 (クエリプラン) を現在より多く出力する # (SQLite、MySQL、PostgreSQLで動作) config.active_record.auto_explain_threshold_in_seconds = 0.5
7.3 config/environments/test.rb
mass_assignment_sanitizer
設定をconfig/environments/test.rb
にも追加する必要があります。
# Active Recordのモデルをマスアサインメントから保護するために例外を発生する config.active_record.mass_assignment_sanitizer = :strict
7.4 vendor/plugins
vendor/plugins
はRails 3.2で非推奨となり、Rails 4.0では完全に削除されました。Rails 3.2へのアップグレードでは必須ではありませんが、今のうちにプラグインをgemにエクスポートしてGemfileに追加するのがよいでしょう。理由があってプラグインをgemにしないのであれば、プラグインをlib/my_plugin/*
に移動し、適切な初期化の記述をconfig/initializers/my_plugin.rb
に書いてください。
7.5 Active Record
:dependent => :restrict
オプションはbelongs_to
から削除されました。関連付けられたオブジェクトがある場合にこのオブジェクトを削除したくない場合は、:dependent => :destroy
を設定し、関連付けられたオブジェクトのdestroyコールバックとの関連付けがあるかどうかを確認してからfalse
を返すようにします。
8 Rails 3.0からRails 3.1へのアップグレード
Railsアプリケーションのバージョンが3.0より前の場合、まず3.0へのアップグレードを完了してからRails 3.1へのアップグレードにとりかかってください。
以下の変更は、Rails 3.1.xの最新版であるRails 3.1.12にアップグレードするためのものです。
8.1 Gemfile
Gemfile
を以下のように変更します。
gem 'rails', '3.1.12' gem 'mysql2' # 新しいアセットパイプラインで必要 group :assets do gem 'sass-rails', '~> 3.1.7' gem 'coffee-rails', '~> 3.1.1' gem 'uglifier', '>= 1.0.3' end # Rails 3.1からjQueryがデフォルトのJavaScriptライブラリになる gem 'jquery-rails'
8.2 config/application.rb
アセットパイプラインを使用するために以下の変更が必要です。
config.assets.enabled = true config.assets.version = '1.0'
Railsアプリケーションでリソースのルーティングに"/assets"ルートを使用している場合、コンフリクトを避けるために以下の変更を加えます。
# '/assets'のデフォルト config.assets.prefix = '/asset-files'
8.3 config/environments/development.rb
RJS の設定config.action_view.debug_rjs = true
を削除してください。
アセットパイプラインを有効にしている場合は以下の設定を追加します。
# 開発環境ではアセットを圧縮しない config.assets.compress = false # アセットで読み込んだ行を展開する config.assets.debug = true
8.4 config/environments/production.rb
以下の変更はほとんどがアセットパイプライン用です。詳細については アセットパイプライン ガイドを参照してください。
# JavaScriptとCSSを圧縮する config.assets.compress = true # プリコンパイル済みのアセットが見当たらない場合にアセットパイプラインにフォールバックしない config.assets.compile = false # アセットURLのダイジェストを生成する config.assets.digest = true # Rails.root.join("public/assets")へのデフォルト # config.assets.manifest = 該当するパス # 追加のアセット (application.js、application.cssおよびすべての非JS/CSSが追加済み) をプリコンパイルする # config.assets.precompile += %w( admin.js admin.css ) # アプリケーションへのすべてのアクセスを強制的にSSLにし、Strict-Transport-Securityとセキュアクッキーを使用する # config.force_ssl = true
8.5 config/environments/test.rb
テスト環境に以下を追加することでテストのパフォーマンスが向上します。
# Cache-Controlを使用するテストで静的アセットサーバーを構成し、パフォーマンスを向上させる config.public_file_server.enabled = true config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' }
8.6 config/initializers/wrap_parameters.rb
ネストしたハッシュにパラメータを含めたい場合は、このファイルに以下のコンテンツを含めて追加します。新しいアプリケーションではこれがデフォルトになります。
# このファイルを変更後サーバーを必ず再起動してください。 # このファイルにはActionController::ParamsWrapper用の設定が含まれており # デフォルトでオンになっています。 # JSON用にパラメータをラップします。:formatに空配列を設定することで無効にできます。 ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] end # JSONのルート要素をデフォルトで無効にする ActiveSupport.on_load(:active_record) do self.include_root_in_json = false end
8.7 config/initializers/session_store.rb
何らかの新しいセッションキーを設定するか、すべてのセッションを削除するかのどちらかにする必要があります。
# config/initializers/session_store.rbに以下を設定する AppName::Application.config.session_store :cookie_store, key: 'SOMETHINGNEW'
または
$ bin/rake db:sessions:clear
8.8 ビューのアセットヘルパー参照から:cacheオプションと:concatオプションを削除する
- Asset Pipelineの:cacheオプションと:concatは廃止されました。ビューからこれらのオプションを削除してください。