はじめに
さて、また大変なメジャーアップデートです。かなりの変更がありますので、ゆっくりやっていきましょう。Ruby は最低限の 2.2.2 までは上げています。
Rails のアップデート
まず、Gemfile の rails を5.0 の最終である 5.0.7.2 に変更します。
gem 'rails', '5.0.7.2'
bundle update します。
bundle update
相変わらず、include でエラーが出るので外した上で、update します。5.0 からは rails という namespace が deprecated となったので、コマンドが変えておきます。
env THOR_DIFF=vimdiff bin/rake app:update
ApplicationRecord の作成と、継承の変更
ApplicationRecord を追加するとともに、全部の app/models/*.rb を修正する必要があります。これはいつもように vim のマクロで一括変換できそうです。
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を継承するように変更し、動作を確認してください。
throw(:abort) によるコールバックチェーンの停止
コールバックで false を返すと、その後の処理が停止していましたが、Rails 5.0 からは明示的に throw(:abort) をする必要があります。これも vim のマクロで置き換えしてしまいます。
Rails 4.2では、Active RecordやActive Modelで「before」系コールバックがfalseを返すと、すべてのコールバックチェーンが停止する仕様でした。この場合、以後「before」系コールバックは実行されず、コールバック内にラップされているアクションも実行されません。
Rails 5.0ではこの副作用が修正され、Active RecordやActive Modelのコールバックでfalseが返ってもコールバックチェーンが停止しなくなりました。その代わり、今後コールバックチェーンはthrow(:abort)で明示的に停止する必要があります。
before_filter → before_action の修正
アップグレードガイドには書いていませんが、リリースノートの非推奨のところに書いてありました。警告がうるさいので、このバージョンで、before, after ともに修正しておきます。
DEPRECATION WARNING: before_filter is deprecated and will be removed in Rails 5.1. Use before_action instead. (called from <class:ApplicationController> at /opt/webcitc/app/controllers/application_controller.rb:3)
filterコールバックをすべて非推奨に指定。今後は*actionコールバックを使用。 (Pull Request)
hide_action の削除
また、hide_action でエラーになりました。https://apidock.com/rails/ActionController/HideActions/ClassMethods/hide_action を見ると、5.0 で亡くなったようです。自分で書いた記憶がないので、業者が追加したものだと思います。これは普通に private メソッドにすればいいだけですね。
This method has been completely removed from Rails 5 onwards
Completely removed from Rails from 5 onwards. See issue: github.com/rails/rails/issues/18336
Just remove from your codebase, or protect with
private
keyword
ヘルパーメソッドの一部をrails-controller-testingに移転
bin/rspec したところ、以下のエラーが出ました。
NoMethodError: assert_template has been extracted to a gem. To continue using it, add `gem 'rails-controller-testing'` to your Gemfile.
これですね。とりあえず、rails-controller-testing を入れればいいだけなので、Gemfile を修正します。
assignsメソッドとassert_templateメソッドはrails-controller-testing gemに移転しました。これらのメソッドを引き続きコントローラのテストで使いたい場合は、Gemfileにgem 'rails-controller-testing'を追加してください。
positional arguments の修正
これも 5.1 からの削除ですが、DEPRECATION WARNING を消しておきます。引数を params というハッシュに変更する必要があるようです。これも vim のマクロでなんとかなりそうです。
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" },
Time 型のタイムゾーンについて
params の修正をしていたら、あるファイルで以下の警告が出ました。Rails 5.0 からは Time もタイムゾーンを考慮するようになるとのことです(Rails 5.1 から time 型の列もタイムゾーン考慮するようになるとのこと - 飲んだり寝たり)。ここを見ると単に Time と書いた時でも、Time.zone に書き換えるとのこと。
DEPRECATION WARNING: Time columns will become time zone aware in Rails 5.1. This still causes `String`s to be parsed as if they were in `Time.zone`, and `Time`s to be converted to `Time.zone`.
最近書いたコードはみんな Time.zone と書いていますが、過去のものは Time で書かれたものが多いです。とりあえずテストを通すため、Time.zone への書き換えはしないでおきます。ただ、内部で JST に置き換える無駄な処理が多くの場所で入っているので、最新版になったら修正することにします。
config.active_record.time_zone_aware_types = [:datetime]
reload に関する修正
これまで、関連の再読み込みをするときに obj.hoges(true)
やobj.foo(true)
のようにして reload をしていましたが、この部分で以下の警告が出ていました。これらはobj.reload.hoges
や obj.reload_foo
のように修正する必要があるようです。これも(true)で全検索して潰していこうと思います。
DEPRECATION WARNING: Passing an argument to force an association to reload is now deprecated and will be removed in Rails 5.1. Please call `reload` on the result collection proxy instead.
params[:hoge] → params['hoge'] の修正
失敗系のテストで params[:hoge] を nil などにするテストをしていました。params のキーが文字列に変わっているようなので、失敗テストがことごとく失敗しています。これもエラーになった場所からマクロで修正してしまいます。
Active Recordのbelongs_toはデフォルトオプションで必須
belongs_to は必須になり、null になる場合には、「optional(true)」が必要になります。 新しいアプリケーションでは必須ですが、既存のものは config を書き換えない限りはまだこのままいけます。とりあえずデフォルトが true になるまで、対応はペンディングします。
関連付けが存在しない場合、belongs_toでバリデーションエラーが発生するようになりました。
新しいアプリケーションでは、このデフォルト設定が自動で有効になります。この設定を既存のアプリケーションに追加するには、イニシャライザでこの機能をオンにする必要があります
config.active_record.belongs_to_required_by_default = true
おわりに
細かいことはまだありそうですが、テストは少しずつ修正しながらも全部通すことができました。メジャーアップデートで、修正箇所が山のようにあったので、流石に 1日仕事になりました。時間は少し伸びたくらいであまり変わりませんでした。
Finished in 12 minutes 5 seconds (files took 7.23 seconds to load) 7726 examples, 0 failures, 98 pending
(12/29追記) Segmentation fault の原因が hpricot だとわかったので、 Ruby 2.4.5 でやり直してみました。時間はほぼ変わりませんでした。
Finished in 12 minutes 6 seconds (files took 5.5 seconds to load) 7726 examples, 0 failures, 98 pending
gem の推移はこんな感じです。
gem_name | ver4.2 | ver5.0 | changed |
---|---|---|---|
actioncable | 5.0.7.2 | + | |
actionmailer | 4.2.11.3 | 5.0.7.2 | ↑ |
actionpack | 4.2.11.3 | 5.0.7.2 | ↑ |
actionview | 4.2.11.3 | 5.0.7.2 | ↑ |
activejob | 4.2.11.3 | 5.0.7.2 | ↑ |
activemodel | 4.2.11.3 | 5.0.7.2 | ↑ |
activerecord | 4.2.11.3 | 5.0.7.2 | ↑ |
activesupport | 4.2.11.3 | 5.0.7.2 | ↑ |
arel | 6.0.4 | 7.1.4 | ↑ |
bcrypt | 3.1.16 | 3.1.16 | = |
better_errors | 2.9.1 | 2.9.1 | = |
binding_of_caller | 0.8.0 | 0.8.0 | = |
brakeman | 4.4.0 | 4.4.0 | = |
builder | 3.2.4 | 3.2.4 | = |
choice | 0.2.0 | 0.2.0 | = |
ci_reporter | 2.0.0 | 2.0.0 | = |
coderay | 1.1.3 | 1.1.3 | = |
coffee-rails | 4.2.2 | 4.2.2 | = |
coffee-script | 2.4.1 | 2.4.1 | = |
coffee-script-source | 1.12.2 | 1.12.2 | = |
concurrent-ruby | 1.1.7 | 1.1.7 | = |
crass | 1.0.6 | 1.0.6 | = |
database_cleaner | 1.8.5 | 1.8.5 | = |
debug_inspector | 0.0.3 | 0.0.3 | = |
devise | 3.5.10 | 4.0.0.rc2 | ↑ |
devise-encryptable | 0.2.0 | 0.2.0 | = |
devise_ldap_authenticatable | 0.8.7 | 0.8.7 | = |
diff-lcs | 1.4.4 | 1.4.4 | = |
docile | 1.3.4 | 1.3.4 | = |
dotenv | 2.7.6 | 2.7.6 | = |
erubi | 1.10.0 | 1.10.0 | = |
erubis | 2.7.0 | 2.7.0 | = |
execjs | 2.7.0 | 2.7.0 | = |
factory_bot | 4.11.1 | 4.11.1 | = |
factory_bot_rails | 4.11.1 | 4.11.1 | = |
ffi | 1.12.2 | 1.12.2 | = |
formatador | 0.2.5 | 0.2.5 | = |
globalid | 0.4.2 | 0.4.2 | = |
guard | 2.15.1 | 2.15.1 | = |
guard-compat | 1.2.1 | 1.2.1 | = |
guard-rspec | 4.7.3 | 4.7.3 | = |
haml | 4.0.7 | 4.0.7 | = |
haml-rails | 1.0.0 | 1.0.0 | = |
hpricot | 0.8.6 | 0.8.6 | = |
html2haml | 2.2.0 | 2.2.0 | = |
i18n | 0.9.5 | 1.5.1 | ↑ |
interception | 0.5 | 0.5 | = |
jquery-rails | 4.4.0 | 4.4.0 | = |
json | 2.5.1 | 2.5.1 | = |
kaminari | 1.2.1 | 1.2.1 | = |
kaminari-actionview | 1.2.1 | 1.2.1 | = |
kaminari-activerecord | 1.2.1 | 1.2.1 | = |
kaminari-core | 1.2.1 | 1.2.1 | = |
listen | 3.0.8 | 3.0.8 | = |
loofah | 2.8.0 | 2.8.0 | = |
lumberjack | 1.0.13 | 1.0.13 | = |
2.7.1 | 2.7.1 | = | |
method_source | 0.9.2 | 0.9.2 | = |
mini_mime | 1.0.2 | 1.0.2 | = |
mini_portile2 | 2.4.0 | 2.4.0 | = |
minitest | 5.14.2 | 5.14.2 | = |
nenv | 0.3.0 | 0.3.0 | = |
net-ldap | 0.17.0 | 0.17.0 | = |
nio4r | 2.3.1 | 2.3.1 | = |
nokogiri | 1.9.1 | 1.9.1 | = |
notiffany | 0.1.3 | 0.1.3 | = |
orm_adapter | 0.5.0 | 0.5.0 | = |
pg | 0.20.0 | 0.20.0 | = |
power_assert | 1.2.0 | 1.2.0 | = |
pry | 0.12.2 | 0.12.2 | = |
pry-doc | 1.1.0 | 1.1.0 | = |
pry-rails | 0.3.9 | 0.3.9 | = |
pry-rescue | 1.5.2 | 1.5.2 | = |
public_suffix | 3.1.1 | 3.1.1 | = |
puma | 5.1.1 | 5.1.1 | = |
rack | 1.6.13 | 2.1.4 | ↑ |
rack-cache | 1.9.0 | 1.9.0 | = |
rack-test | 0.6.3 | 0.6.3 | = |
rails | 4.2.11.3 | 5.0.7.2 | ↑ |
rails-controller-testing | 1.0.5 | + | |
rails-deprecated_sanitizer | 1.0.3 | - | |
rails-dom-testing | 1.0.9 | 2.0.3 | ↑ |
rails-erd | 1.6.0 | 1.6.0 | = |
rails-html-sanitizer | 1.3.0 | 1.3.0 | = |
railties | 4.2.11.3 | 5.0.7.2 | ↑ |
rake | 13.0.3 | 13.0.3 | = |
rb-fsevent | 0.10.4 | 0.10.4 | = |
rb-inotify | 0.10.1 | 0.10.1 | = |
rb-readline | 0.5.5 | 0.5.5 | = |
rdoc | 6.2.0 | 6.2.0 | = |
redcarpet | 3.5.1 | 3.5.1 | = |
responders | 2.4.1 | 2.4.1 | = |
rspec | 3.10.0 | 3.10.0 | = |
rspec-core | 3.10.0 | 3.10.0 | = |
rspec-expectations | 3.10.0 | 3.10.0 | = |
rspec-mocks | 3.10.0 | 3.10.0 | = |
rspec-rails | 4.0.1 | 4.0.1 | = |
rspec-support | 3.10.0 | 3.10.0 | = |
ruby-graphviz | 1.2.4 | 1.2.4 | = |
ruby_parser | 3.15.0 | 3.15.0 | = |
sass | 3.7.4 | 3.7.4 | = |
sass-listen | 4.0.0 | 4.0.0 | = |
sass-rails | 6.0.0 | 6.0.0 | = |
sassc | 2.4.0 | 2.4.0 | = |
sassc-rails | 2.1.2 | 2.1.2 | = |
sexp_processor | 4.15.1 | 4.15.1 | = |
shellany | 0.0.1 | 0.0.1 | = |
simplecov | 0.17.1 | 0.17.1 | = |
simplecov-html | 0.10.2 | 0.10.2 | = |
simplecov-rcov | 0.2.3 | 0.2.3 | = |
spring | 2.0.2 | 2.0.2 | = |
spring-commands-rspec | 1.0.4 | 1.0.4 | = |
sprockets | 3.7.2 | 3.7.2 | = |
sprockets-rails | 3.2.2 | 3.2.2 | = |
test-unit | 3.3.8 | 3.3.8 | = |