839の日記

趣味の話を書くブログです。

Rails 6.1, Ruby3.0.0(rc1)に上げるまでに踏んだ問題

趣味で動かしているRails6.0.x、Ruby 2.7.1のアプリ3つをRails 6.1、Ruby 3.0.0(rc1)にまで上げようと試みた。 そのときに遭遇した問題をまとめたもの。

ひとまずRails 6.1、Ruby 2.7.2まで上げることにした。 以下、その過程で踏んだ問題。

rails aborted! LoadError: cannot load such file -- listen

rails app:update を叩いたときに出てきた。

gem 'listen'

を追加。

Rails 6.1はActiveStorage周りのスキーマも変わっていて、 rails app:update を実行するとマイグレーションファイルが追加されるので実行をお忘れなく。

NoMethodError: undefined method `parent' for MyApplication::Application:Class

rails db:migrate を実行したときにrails-erdで出る。 Rails 6.1 support · Issue #363 · voormedia/rails-erd · GitHub の通り、issueは立っているが作者が1年ぐらい更新してないので更新されるか望み薄。 とりあえずフォーク版で修正してくれていたのでそれを使うようにした。

  gem 'rails-erd', github: 'guapolo/rails-erd'

uninitialized constant NestedForm::BuilderMixin (NameError)

同じく rails db:migrate の時に発生。rails_admin の問題の様子。 config/initializers/rails_admin.rb に2行のrequireを追加した。

refs: uninitialized constant NestedForm::BuilderMixin · Issue #887 · sferik/rails_admin · GitHub

require "nested_form/engine"
require "nested_form/builder_mixin"

NoMethodError: undefined method `assert_nothing_raised'

RSpecのSystemSpecで出るようになっていた。 rspec - Rails 6.1 upgrade: undefined method `assert_nothing_raised' - Stack Overflow これと同じ問題だったのでspec/rails_helper.rb に以下を追加

  config.include ActiveSupport::Testing::Assertions

SystemStackError - stack level too deep

developmentで試しに動作確認しようとしたら出た。

stacktrace的に meta_request というGemが怪しかったので試しにオフにしたら解決。 特に使っていなかったのでそのまま削除。

activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:174:in `block in as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:173:in `each'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:173:in `as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:57:in `as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:174:in `block in as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:173:in `each'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:173:in `as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:174:in `block in as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:173:in `each'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:173:in `as_json'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:57:in `as_json'
activesupport (6.1.0) lib/active_support/json/encoding.rb:35:in `encode'
activesupport (6.1.0) lib/active_support/json/encoding.rb:22:in `encode'
activesupport (6.1.0) lib/active_support/core_ext/object/json.rb:42:in `to_json'
meta_request (0.7.2) lib/meta_request/event.rb:46:in `block in json_encodable'
meta_request (0.7.2) lib/meta_request/event.rb:66:in `block in transform_hash'
meta_request (0.7.2) lib/meta_request/event.rb:60:in `each'
meta_request (0.7.2) lib/meta_request/event.rb:60:in `inject'
meta_request (0.7.2) lib/meta_request/event.rb:60:in `transform_hash'
meta_request (0.7.2) lib/meta_request/event.rb:38:in `json_encodable'
meta_request (0.7.2) lib/meta_request/event.rb:15:in `initialize'
meta_request (0.7.2) lib/meta_request/app_notifications.rb:69:in `new'
meta_request (0.7.2) lib/meta_request/app_notifications.rb:69:in `block in subscribe'
meta_request (0.7.2) lib/meta_request/app_notifications.rb:81:in `block in subscribe'

NameError: uninitialized constant ActiveJob::Logging::LogSubscriber

ActiveJobの引数に巨大な値を指定するとログが一瞬で埋まるのでsnipするために挟んでいた。 6.0.xから6.1でこの辺が変わっていたみたい。

diff --git a/config/initializers/active_job_custom_logger.rb b/config/initializers/active_job_custom_logger.rb
index 1b352a6..856338a 100644
--- a/config/initializers/active_job_custom_logger.rb
+++ b/config/initializers/active_job_custom_logger.rb
@@ -1,4 +1,4 @@
-require 'active_job/logging'
+require 'active_job/log_subscriber'
 
 module ActiveJobCustomLogger
   def args_info(job)
@@ -9,4 +9,4 @@ module ActiveJobCustomLogger
   end
 end
 
-ActiveJob::Logging::LogSubscriber.prepend(ActiveJobCustomLogger)
+ActiveJob::LogSubscriber.prepend(ActiveJobCustomLogger)

ArgumentError: You tried to define an enum named "bar_status" on the model "Hoge", but this will generate a instance method "_?", which is already defined by another enum.

enum値に日本語を使ってると(正確には英数字以外を使っていると)正規表現で消されてしまって重複メソッド扱いになりエラーとなる。 https://github.com/rails/rails/blob/v6.1.0/activerecord/lib/active_record/enum.rb#L205

一応issueにコメントだけしたけど、コーナーケースすぎるのでそもそもコメントしようか悩んだ…。 背景的にはローカライズが必要ない(する予定がない)のでそのまま日本語を入れていた。

https://github.com/rails/rails/issues/40804#issuecomment-751440989

2021/01/09追記

kamipoさんが6.1.1で直してくれた。感謝。

manifest unknown

Ruby, Railsと直接関係ないポカミス。 masterにマージしてimageを作る際に出た。

ruby:2.7.2-alpine3.10 なんてイメージはないので ruby:2.7.2-alpine3.12 に修正。

Step 1/22 : FROM ruby:2.7.2-alpine3.10
manifest for ruby:2.7.2-alpine3.10 not found: manifest unknown: manifest unknown

rails aborted! LoadError: Error loading shared library liblzma.so.5: No such file or directory (needed by /usr/local/bundle/gems/nokogiri-1.10.10/lib/nokogiri/nokogiri.so) - /usr/local/bundle/gems/nokogiri-1.10.10/lib/nokogiri/nokogiri.so

Rails 6.1、Ruby 2.7.2の段階で一回デプロイしておいた。 趣味なので多少エラーが出ても良いし、Ruby 3に関係ないところで問題があるなら切り分けて確認しておきたいため。

どこかで見たことがあるエラー、 prod環境の rails db:migrate 時に発生。 alpineだとありがちなイメージがあったのでこの機会にslim-busterに移行した。

イメージサイズが135MB->285MBになってしまった…。 とはいえ特に問題なく普通に動くのがコンテナのいいところ。

Ruby 3化

バージョン管理にasdfを使っているが、3.0.0が選べなかったので調べてたらここに行き着いた。 Increment ruby-build for Ruby 3.0.0 support by f440 · Pull Request #192 · asdf-vm/asdf-ruby · GitHub ASDF_RUBY_BUILD_VERSION=v20201225 asdf install ruby 3.0.0 でインストール。

まず起動しようとするとcannot load such file -- webrick/httputils (LoadError) が出た。 全く心当たりが無いのでstacktraceを見ると、

/vendor/bundle/ruby/3.0.0/gems/mechanize-2.7.6/lib/mechanize.rb:12:in `<main>

太古に使ってたGemなので削除。

次に cannot load such file -- binding_of_caller.bundle (LoadError) が出た。 stacktraceを見ると、

/vendor/bundle/ruby/3.0.0/gems/binding_of_caller-0.8.0/lib/binding_of_caller.rb:9:in `<main>'

BetterErrorsを使うために入れていたけど、試しに消してみる。 Gemfile.lockを見ると、

    pry-stack_explorer (0.5.1)
      binding_of_caller (~> 0.7)

の依存でまだ残っていたのでpry-stack_explorerも消す。 これでようやくrails sで起動するようになった。

最近はirbも進化してるし、productionではpryを使ってないのでirbに移行しよう。 BetterErrorsも便利だったけどweb-consoleで十分かな。という断捨離の気持ちが得られた。 Rails触りはじめの頃に使ったアプリなので不要なgemがたくさん入ってしまっている…。

web-consoleはVimiumと干渉してまともにタイプできないことが一番きつい。 jsで入力キーを取得してpreタグの中で入れ込むような挙動になっているようなので、素直にinputタグにしてくれたら大丈夫そうだけど、色々フックされてるっぽいのでややこしそう…。 あるいは一時的にVimiumをオフにするショートカットキーなどがあればそれで対応する形になるか…。

Ruby公式もテスト用の circleci/ruby もRC版しかなかったので一旦RC1のイメージを使うようにした。

ruby:3.0.0-rc1-slim-busterにはgitが入っていなかったので、gitをapt-get installに追加。 この状態でデプロイして特に問題なく動作したので、あとは正式版のイメージが出たら切り替えようかな、というぐらい。 ちょくちょく動かないものがあって断捨離をしたけど、結果的に良かった気がする。

全体の所感としては依存が多くなるほどアップデートのときに大変で運用コストがかかるので極力依存を増やさずにものを作ろうという気持ちに改めてなった。 あと複数アプリで更新作業をしてると rails app:update の実行で config/environments の差分をちゃんと反映する作業が一番精神的に大変だった。 カスタム設定は末尾に記載してなるべく差分反映の影響を受けないところに置いておくのがいいのかもしれない。