事象
Railsのプロジェクトを5.2.3にあげたら、CIサーバーのジョブが失敗した。
中身を見たら、DBをセットアップするところに以下のエラーになったよう:
bundle exec rails db:create RAILS_ENV=test
bundle exec rails db:structure:load --trace RAILS_ENV=test
...
rails aborted!
TinyTds::Error: Database 'project_name_test' does not exist. Make sure that the name is entered correctly.
rails db:create
でDBが存在しないので怒られたっぽい。ないから作るのに…
ローカルで実行してみたら、テスト環境のみこの事象が発生した。
原因
長年で磨き上げたググる力で探してみたら、原因はこのIssueで書いている内容だそうだ。
https://github.com/rails/rails/issues/32870#issuecomment-413388302
ざっくり言うと、Railsで config.after_initialize
という処理のタイミングをアプリ初期化後に制御できるメソッドがあるが、 このメソッドはrakeタスクに適用しない。ただし5.2までは一部そもそも完全に初期化しなくても実行できるrakeタスクもあった(db:create
はその一つ)。
5.2以降はその挙動が変わって(ていうか本来あるべき挙動になって)、db:create
を含め全てのrakeタスクも初期化が必要になった。
ところでFactoryBotでは config.after_initialize
でFactoryの定義をロードするような処理が入っているらしい。Factory定義→モデル定義→ここでテーブルが存在しているかどうかのチェックが入っているので、db:create
の前にテーブルの存在チェックを行い、今回のエラーになった。(むしろ今まではただ逃げれていただけだ…)
解決
Issueに書いている解決策を参考して、デフォルトではなく必要な時だけFactoryBotを呼ぶようにする。
Gemfileに
gem 'factory_bot_rails', require: false
そして使う場所に(自分の場合はspec/spec_helper.rb
)
require 'factory_bot_rails'
これでうまくDB作れた。