Ruby on Rails 5.0 アップグレード対応まとめ
モバイルアプリサービス部の五十嵐です。
railsアプリケーションのバージョンアップを行う機会がありましたので、対応内容をまとめておきます。何かのお役に立てば幸いです。
バージョン
rails '4.2.5.1' → '5.0.1'
はじめる前に参考にしたサイト
- Rails アップグレードガイド | Rails ガイド
rubyonrails.org の 日本語訳です。 - これでもう怖くない!?Rails 4.1からRails 5.0にアップグレードする手順を動画付きで解説します - Qiita
動画で解説されているのが大変ありがたかったです。
作戦
- テストカバレッジを確認する
- アップグレードガイドを確認する
- Rails及び依存ライブラリのバージョンアップ
- アップデートタスクを実行する
- 変更箇所と非推奨箇所を修正する
- 最終確認
テストカバレッジを確認する
はじめる前にテストが全てパスすることを確認します。さらに、テストを全てパスしてたとしても、テストが通っていない箇所で問題が起きていては困るので、テストが不足している箇所がないか確認しました。
プロジェクトでは simplecov でテストカバレッジを見える化をしていましたので、この結果によりテストが不足してそうな箇所がないか確認し、足りなければテストを追加し事前にカバレッジを上げておくようにしました。
アップグレードガイドを確認する
rubyonrails.org の 日本語訳がありますので、こちらでアップグレードの方法を確認します。
https://railsguides.jp/upgrading_ruby_on_rails.html
Rails及び依存ライブラリのバージョンアップ
いよいよrailsのアップデートです。Gemfileにアップデートするgemのバージョンを書いて bundle update
をします。railsの場合、同時にいくつかの依存関係のあるgemもアップデートする必要があると思います。このプロジェクトでは最終的に以下のgemをアップデートすることで、依存関係が解決されました。
$ bundle update rails coffee-rails devise railties ... Bundle updated!
また、どうしても依存関係が解決できないgemもありました。こちらはrails本体に統合されたようなので削除しました。
-gem 'quiet_assets'
アップデートタスクを実行する
次に app:update
を実行します。これを実行することでbinファイルや設定ファイルのマイグレートを行うことができます。
処理は対話的に行われます。既存ファイルとconflictがある場合は、どのようにするかを問われます。ここでは細かい作業はできませんので、基本的には y(上書き)
を選択して、あとでgitなどで変更差分を確認するのが良いと思います。
$ bin/rails app:update ... conflict config/boot.rb Overwrite /.../config/boot.rb? (enter "h" for help) [Ynaqdh] d - ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) + ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) ...
このような作業が続きます。
変更箇所と非推奨箇所を修正する
テストがすべて通るようになるまで、エラー及びDeprecatedを解消していきます。
gem 'devise' のバージョンアップに伴う変更①
メッセージ
bundler: failed to load command: rspec (/.../vendor/bundle/ruby/2.2.0/bin/rspec) NoMethodError: undefined method `devise' for User:Class
対処
DeviseのUserClassに extend Devise::Models
を追加しました。
https://github.com/plataformatec/devise/issues/3877
gem 'devise' のバージョンアップに伴う変更②
メッセージ
DEPRECATION WARNING: [Devise] bypass option is deprecated and it will be removed in future version of Devise. Please use bypass_sign_in method instead. Example: bypass_sign_in(user) (called from update_password at /.../app/controllers/users/registrations_controller.rb:14)
対処
メッセージの通り、sign_inメソッドをbypass_sign_inメソッドに変更します。
- sign_in(user, bypass: true) + bypass_sign_in(user)
gem 'rails' のバージョンアップに伴う変更①
メッセージ
DEPRECATION WARNING: ActiveRecord::Base.raise_in_transactional_callbacks= is deprecated, has no effect and will be removed without replacement. (called from <top (required)> at /.../app/models/application_record.rb:1)
対処
app/config/application.rb の config.raise_in_transactional_callbacks = true
のDEPRECATION WARNINGです。この設定項目は役目を終えたため削除しました。
http://edgeguides.rubyonrails.org/upgrading_ruby_on_rails.html
gem 'rails' のバージョンアップに伴う変更②
メッセージ
DEPRECATION WARNING: `:nothing` option is deprecated and will be removed in Rails 5.1. Use `head` method to respond with empty response body. (called from test_set_userinfo at /.../spec/concerns/userinfo_settable_spec.rb:11)
対処
renderメソッドの :nothing
オプションが使えなくなり、代わりに headメソッドを使うようになりました。
def nothing - render nothing: true + head :no_content end
さらにrspecでcontrollerのテストを実行するには gem 'rails-controller-testing' が必要になりましたので追加しました。
https://railsguides.jp/upgrading_ruby_on_rails.html
gem 'rails' のバージョンアップに伴う変更③
メッセージ
DEPRECATION WARNING: Method with_indifferent_access is deprecated and will be removed in Rails 5.1
対処
ActionController::Parameters は今後 HashWithIndifferentAccess を継承しなくなるため、with_indifferent_accessメソッドは使えなくなるということです。
https://railsguides.jp/upgrading_ruby_on_rails.html
代替として、ActionController::Parameters#to_unsafe_h を使うことができます。
http://api.rubyonrails.org/v5.0.1/classes/ActionController/Parameters.html
gem 'rspec-rails' のバージョンアップに伴う変更
メッセージ
DEPRECATION WARNING: Using positional arguments in functional tests has been deprecated, in favor of keyword arguments, and will be removed in Rails 5.1. Deprecated style: get :show, { id: 1 }, nil, { notice: "This is a flash message" } New keyword style: get :show, params: { id: 1 }, flash: { notice: "This is a flash message" }, session: nil # Can safely be omitted.
対処
メッセージの通り、引数のキーワードを明示することで解決します。
gem 'webmock' のアップデートに伴う変更
メッセージ
getaddrinfo: nodename nor servname provided, or not known
対処
webmock 2.0.0 より、Basic認証を含むリクエストのスタブの作り方が変更されました。いままではリクエストURLに含めていましたが、2.0.0からはwithメソッドで指定するようになりました。
- stub_request(:get, "user:pass@www.example.com") + stub_request(:get, "www.example.com").with(basic_auth: ['user', 'pass'])
https://github.com/bblimke/webmock/blob/master/CHANGELOG.md#200
最終確認
テストカバレッジを確認し、テストで網羅されていないロジックの部分は手動で確認します。
まとめ
rails本体のアップデートによる影響は意外と少なく、依存するライブラリの破壊的な機能変更を調べるほうが大変でした。メジャーバージョンが上がっている場合には特に注意が必要です。