倒れるときは前のめり。

カレーが好きです。

Rails on Docker な素振り環境の Rails バージョンアップをした(v5.1.4 => v5.2.0)

タイトルの通り。所詮サンプルアプリケーションだし楽勝かな…と思ったが意外なところで躓いたので、備忘録として残しておく。

5.2.0 に上げる

Gemfile の Rails のバージョン指定を ~> 5.2.0 に修正して、

bundle update rails

からの

bin/rails app:update

いろいろとファイルが書き換えられてしまうので、よしなに git diff しながら目視で確認していく。

テストが落ちる

覚悟はしていたのだけど、Rails のバージョン上げたらテストが落ちるようになった。エラーメッセージを読みつつ binding.pry を適宜はさみながらデバッグして直していった。

Helper Spec が落ちる

たとえばこれ

https://github.com/cheezenaan-sandbox/sample_app_rev4/commit/1925113

Failures:

  1) UsersHelper gravatar_for when user is present when email is present
     Failure/Error: end

     ArgumentError:
       Can't resolve image into URL: undefined method `to_model' for #<Pathname:0x0000556238b7cd58>
       Did you mean?  to_yaml
     # ./app/helpers/users_helper.rb:11:in `gravatar_for'
     # ./spec/helpers/users_helper_spec.rb:7:in `block (3 levels) in <top (required)>'
     # ./spec/helpers/users_helper_spec.rb:31:in `block (5 levels) in <top (required)>'
     # -e:1:in `<main>'
     # ------------------
     # --- Caused by: ---
     # NoMethodError:
     #   undefined method `to_model' for #<Pathname:0x0000556238b7cd58>
     #   Did you mean?  to_yaml
     #   ./app/helpers/users_helper.rb:11:in `gravatar_for'

v5.2.0 へ上げた際に落ちるようになった。どうやら image_tag が怪しそうので git diff v5.1.4..v5.2.0 actionview/lib --stat しながら Rails のコードを追っていくと、AssetTagHelper#image_tag に修正入ってた。たぶん ActiveStorage もろもろの対応の影響なんだろう。

# actionview/lib/action_view/helpers/asset_tag_helper.rb
def image_tag(source, options = {})
  options = options.symbolize_keys
  check_for_image_tag_errors(options)
  skip_pipeline = options.delete(:skip_pipeline)

  # このへんが v5.2.0 へ向けて追加された箇所っぽい
  options[:src] = resolve_image_source(source, skip_pipeline)

  if options[:srcset] && !options[:srcset].is_a?(String)
    options[:srcset] = options[:srcset].map do |src_path, size|
      src_path = path_to_image(src_path, skip_pipeline: skip_pipeline)
      "#{src_path} #{size}"
    end.join(", ")
  end

  options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
  tag("img", options)
end

ref. https://github.com/rails/rails/compare/v5.1.4...v5.2.0#diff-d36c3bf0d0a61b0b5dbae953a4852ad2R332

image_tag -> resolve_image_sourceからの、 polymorphic_url(source) へ進んだ先で to_model に反応できなくなって落ちるようになったようす。

# actionview/lib/action_view/helpers/asset_tag_helper.rb
def resolve_image_source(source, skip_pipeline)
  if source.is_a?(Symbol) || source.is_a?(String)
    path_to_image(source, skip_pipeline: skip_pipeline)
  else
    polymorphic_url(source) # <= これ
  end
rescue NoMethodError => e
  raise ArgumentError, "Can't resolve image into URL: #{e}"
end

ref.

なので、明示的に Pathname#to_s してやった。ここまでで System Spec 以外のテストが通るようになった。

bin/rspec spec/helpers spec/models spec/requests

System Spec が倒せない

たとえばこんなかんじ。

~/s/g/c/c/sample_app_rev4 » docker-compose exec spring bin/rspec spec/system/static_pages_spec.rb --fail-fast               bump_rails_v5.2 ✔
Running via Spring preloader in process 103

StaticPages
  Home page
Capybara starting Puma...
* Version 3.11.4 , codename: Love Song
* Min threads: 0, max threads: 4
* Listening on tcp://127.0.0.1:40933
    should have title "Ruby on Rails Tutorial Sample App" (FAILED - 1)

Failures:

  1) StaticPages Home page should have title "Ruby on Rails Tutorial Sample App"
     Failure/Error: it { is_expected.to have_title full_title }
       expected "" to include "Ruby on Rails Tutorial Sample App"

     [Screenshot]: tmp/screenshots/failures_r_spec_example_groups_static_pages_home_page_example_at___spec_system_static_pages_spec_rb_13_223.png


     # ./spec/system/static_pages_spec.rb:13:in `block (3 levels) in <top (required)>'
     # -e:1:in `<main>'

Finished in 4.12 seconds (files took 4.18 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/system/static_pages_spec.rb:13 # StaticPages Home page should have title "Ruby on Rails Tutorial Sample App"

Coverage report generated for RSpec to /app/coverage. 17 / 45 LOC (37.78%) covered.

なるほど puma が使われるようになった。

tcp://127.0.0.1:40933…🤔ポート番号がテスト回すたびに変わってるな。このポート番号って Docker で穴を開けてやらんといかんのかな🤔

いろいろと試行錯誤した結果、、Capybara.server_host を明示的に "0.0.0.0" に指定した上で Capybara.server:puma ではなく :webrick にすることで動いた。

# spec/support/capybara.rb
(略)
Capybara.server_host = "0.0.0.0"
# TODO: Use puma as Capybara.server
Capybara.server = :webrick

ref. https://github.com/cheezenaan-sandbox/sample_app_rev4/pull/29/commits/74b13c57

いまいち納得できてないので要調査。

おわりに

Rails バージョンアップ、 いやおうなく Rails 本体のコードを読み進めていくことになるので勉強になるし、これくらいのちっちゃい環境ならいくらでも壊れても問題ないので、積極的にバージョン上げて経験積んでいきたい。

あとは Tachikoma.io で bundle update 自動化していきたい。