Posted at

Ruby 2.2.3 で動いている Rails アプリケーションを Ruby 2.6.2 にアップデートした話

Ruby 2.2.3 で動いている Rails アプリケーションの Ruby バージョンを 2.6.2 まで上げました。対応の多くがアプリケーションが依存する gem によってしまうので、全ての対応が適用できる訳ではありませんが、少しでも参考になれば幸いです。


背景

Ruby 2.2 は2018年3月31日をもってサポートが終了しています。

しかし、対象となったアプリケーションはテストコードが書かれておらず、バージョンアップを行なってもアプリケーションの動作担保が難しい状態でした。

一方で、機能開発を止めることも難しかったため、機能追加を行うたびにテストコードを少しずつ増やしてきました。そして、ようやく最低限のテストコードが揃ったと判断し、今回の Ruby のバージョンアップに踏み切りました。


TL;DR

ruby と、依存する 最低限の gem 10個をアップデートしました。


  • ruby を 2.2.3 -> 2.6.2 にアップデート

  • delayed_job を 4.1.2 -> 4.1.5 にアップデート

  • fog を 1.33.0 -> 1.41.0 にアップデート

  • therubyracer を 0.12.2 -> 0.12.3 にアップデート

  • rails を 4.2.6 -> 4.2.11.1 にアップデート

  • sass-rails を 5.0.4 -> 5.0.7 にアップデート

  • activerecord-session_store を 0.1.1 -> 1.1.3 にアップデート

  • devise を 3.5.10 -> 4.6.2 にアップデート

  • devise_invitable を 1.5.5 -> 1.7.5 にアップデート

  • capistrano を 3.4.0 -> 3.11.0 にアップデート

  • rubocop を 0.60.0 -> 0.62.0 にアップデート


rails server を立ち上げる

まずはローカル環境で rails server が立ち上げることを目指します。以下、発生したエラーとその原因、対応です。


delayed_job


ERROR メッセージ

Bundler::GemRequireError: There was an error while trying to load the gem 'delayed_job_active_record'.

Gem Load Error is: undefined method `yaml_as' for ActiveRecord::Base:Class


原因


対応


fog


ERROR メッセージ

LoadError: cannot load such file -- xmlrpc/client

<略>
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/fog-1.33.0/lib/fog/xenserver/core.rb:23:in `<class:Connection>'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/fog-1.33.0/lib/fog/xenserver/core.rb:22:in `<module:XenServer>'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/fog-1.33.0/lib/fog/xenserver/core.rb:5:in `<module:Fog>'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/fog-1.33.0/lib/fog/xenserver/core.rb:4:in `<top (required)>'


原因


対応


therubyracer


ERROR メッセージ

Bundler::GemRequireError: There was an error while trying to load the gem 'therubyracer'.

Gem Load Error is: wrong argument type Class (expected Module)


原因


対応


rails


ERROR メッセージ

SystemStackError: stack level too deep

/root/repo/vendor/bundle/ruby/2.6.0/gems/activesupport-4.2.6/lib/active_support/core_ext/numeric/conversions.rb:131:in `block (2 levels) in <class:Numeric>'


原因


対応


簡単な動作を確認をする

ここまでで rails server が立ち上がりました :raised_hands: 動作を確認しながら WARN/ERROR メッセージに対応していきます。


sass-rails


WARN メッセージ

DEPRECATION WARNING: Sprockets method `register_engine` is deprecated.

Please register a mime type using `register_mime_type` then
use `register_compressor` or `register_transformer`.
https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors
(called from block (2 levels) in <class:Railtie> at /root/repo/vendor/bundle/ruby/2.6.0/gems/sass-rails-5.0.4/lib/sass/rails/railtie.rb:57)
DEPRECATION WARNING: Sprockets method `register_engine` is deprecated.
Please register a mime type using `register_mime_type` then
use `register_compressor` or `register_transformer`.
https://github.com/rails/sprockets/blob/master/guides/extending_sprockets.md#supporting-all-versions-of-sprockets-in-processors
(called from block (2 levels) in <class:Railtie> at /root/repo/vendor/bundle/ruby/2.6.0/gems/sass-rails-5.0.4/lib/sass/rails/railtie.rb:58)
no_proxy is unsupported


原因


対応

bundle update は完了するが、以下のメッセージが表示される。


Ruby Sass is deprecated and will be unmaintained as of 26 March 2019.


sass-rails のメンテナンスが2019年3月26日をもって終了した。今後は、sass/sassc-ruby: Use libsass with Ruby! を利用することが推奨されている。今回の修正範囲外とするが早めに対応したい。

See also: Ruby Sass Has Reached End-Of-Life « Sass Blog


activerecord-session_store


ERROR メッセージ

Thread.exclusive is deprecated, use Thread::Mutex

/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/activerecord-session_store-0.1.1/lib/active_record/session_store/session.rb:32:in `find_by_session_id'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/activerecord-session_store-0.1.1/lib/action_dispatch/session/active_record_store.rb:66:in `block in get_session'


原因


対応


devise


ERROR メッセージ

SyntaxError - syntax error, unexpected '{', expecting keyword_end

...ter only: [:create, :destroy] { request.env["devise.skip_tim...
... ^
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/devise-3.5.10/app/controllers/devise/sessions_controller.rb:5: syntax error, unexpected '}', expecting keyword_end
..."devise.skip_timeout"] = true }
... ^:
devise (3.5.10) app/controllers/devise/sessions_controller.rb:5:in `'

undefined method `unshift' for nil:NilClass excluded from capture: No host specified, no public_key specified, no project_id specified

NoMethodError (undefined method `unshift' for nil:NilClass):


原因


対応


ERROR メッセージ

NoMethodError - undefined method `for' for #<Devise::ParameterSanitizer:0x00007fc999e94890>:

undefined method `user_omniauth_authorize_path' for #<#<Class:0x00007ffa5913a5c8>:0x00007ffa58bae348>


原因


対応

- devise_parameter_sanitizer.for(:sign_up)

- devise_parameter_sanitizer.for(:sign_in)
+ devise_parameter_sanitizer.permit(:sign_up)
+ devise_parameter_sanitizer.permit(:sign_in)

- user_omniauth_authorize_path(:facebook)

+ user_facebook_omniauth_authorize_path


devise_invitable


ERROR メッセージ

Traceback (most recent call last):

bin/rails: undefined method `attributes_for' for class `Devise::ParameterSanitizer' (NameError)


原因


対応


Rspec や Rubocop などを動かす

ここまででローカル環境での動作確認ができました :raised_hands: ここから Rspec や Rubocop などを動かしていきます。


rubocop


ERROR メッセージ

$ bundle exec rubocop

unknown keywords: whitelist_classes, whitelist_symbols
/Users/tetsuya/.rbenv/versions/2.6.2/lib/ruby/2.6.0/psych.rb:328:in `safe_load'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/config_loader.rb:185:in `yaml_safe_load'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/config_loader.rb:159:in `load_yaml_configuration'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/config_loader.rb:40:in `load_file'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/config_loader.rb:82:in `configuration_from_file'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/config_store.rb:44:in `for'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/cli.rb:187:in `apply_default_formatter'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/lib/rubocop/cli.rb:40:in `run'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/exe/rubocop:13:in `block in <top (required)>'
/Users/tetsuya/.rbenv/versions/2.6.2/lib/ruby/2.6.0/benchmark.rb:308:in `realtime'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/rubocop-0.60.0/exe/rubocop:12:in `<top (required)>'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/bin/rubocop:23:in `load'
/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/bin/rubocop:23:in `<top (required)>'


原因


  • 元を辿ると DHH の black/whitelist って呼び方はよくないんじゃないかという発言に起因する




対応


rubocop-github


ERROR メッセージ

Error: The `Performance/LstripRstrip` cop has been moved to `Style/Strip`

(obsolete configuration found in vendor/bundle/ruby/2.6.0/gems/rubocop-github-0.12.0/config/default.yml, please update it)


原因


対応


検証環境に deploy する

CI も通ったので検証環境に deploy 試みます。


sshkit


ERROR メッセージ

/Users/tetsuya/dev/app_name/vendor/bundle/ruby/2.6.0/gems/sshkit-1.7.1/lib/sshkit/runners/parallel.rb:16:in `rescue in block (2 levels) in execute': Exception while executing as devuser@52.197.98.157: undefined method `<' for nil:NilClass (SSHKit::Runner::ExecuteError)


原因

--


対応


capistrano


WARN メッセージ

[Deprecation Notice] Future versions of Capistrano will not load the Git SCM

plugin by default. To silence this deprecation warning, add the following to
your Capfile after `require "capistrano/deploy"`:

require "capistrano/scm/git"
install_plugin Capistrano::SCM::Git


原因


対応

WARN メッセージにある通り、 Capfile に追記した

+ require "capistrano/scm/git"

+ install_plugin Capistrano::SCM::Git


未解決


WARN メッセージ

/root/repo/vendor/bundle/ruby/2.6.0/gems/activesupport-4.2.11.1/lib/active_support/core_ext/object/duplicable.rb:111: warning: BigDecimal.new is deprecated; use BigDecimal() method instead.


最後に

ruby 2.2.3 から 2.6.2 とマイナーバージョンが4つ上がっただけの様に感じましたが、2.2.3 (2015年8月18日) から 2.6.2 (2019年3月13日リリース) の間に実に3年7ヶ月の時間があり、様々なアップデートが行われていたことがわかりました。

Rails の脆弱性対応も気になっていたので、4.2 系の最新版である 4.2.11.1 にアップデートできたのは安心感があります。

Ruby や Rails を使うメリットの一つに、活発なコミュニティと成熟したエコシステムがあると思います。今後も進化し続けるこの言語/フレームワークを使い続けられる様、しっかりとアップデートに追従していきながら、残念ながら今回はバージョンアップを見送ってしまった gem 達も、アップデートしていきたいと思います。