rails: Unexpected rake task behavior change in Rails 5.2
Steps to reproduce
- Initialize a Rails app (5.2)
- Add
config.after_initialize { raise "foo" }
- Run
rake db:create
Expected behavior
Before 5.2, the after_initialize
block will not be executed so the database can be created successfully
Actual behavior
The app crashed because the after_initialize
block
System configuration
Rails version: 5.2
Ruby version: 2.4.1
Notes
I think this is an issue because before 5.2 we might add some database related logics in after_initialize
block. And since running tasks like db:create
won’t initialize the whole app this can work. Like:
module Sample
class Application < Rails::Application
config.after_initialize do
# connect to database
end
end
end
But after upgrade to 5.2 the code won’t work because the logic will hit the database first before actually execute the rake task (db:create
). And we can’t find this behavior change in changelog or documents.
Also, I found this issue is cause by this commit. Before this commit some of the rake tasks will only run load_config
as prerequisite. But now load_config
has the environment
prerequisite so the app will be fully initialized.
So I think either we change this behavior back, or we should document about it.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 1
- Comments: 18 (12 by maintainers)
Commits related to this issue
- Handle ActiveRecord::NoDatabaseError exception This fixes rake db:create task for rails 5.2 Related Information https://github.com/rails/rails/issues/32870#issuecomment-388619019 — committed to chopraanmol1/public_activity by chopraanmol1 6 years ago
- Rescue ActiveRecord::NoDatabaseError https://github.com/rails/rails/issues/32870 — committed to headwayio/canard by jondkinney 6 years ago
- Rescue ActiveRecord::NoDatabaseError https://github.com/rails/rails/issues/32870 Rescue on `table_exists?` call Without this rescue in place you can’t run `rails db:create`. It’ll fail spectacularl... — committed to headwayio/canard by jondkinney 6 years ago
- 16470: Avoids crashing when running the rake task db:create. There was a behaviour change on rake tasks that avoided the creation of the test database. All initializers are now called from rake tasks... — committed to arvados/arvados by ldipenti 4 years ago
- 16470: Avoids crashing when running db:create in development mode. The 'preload_all_models' initializer is now run even when db:create is called, so it avoids the database to be created on arvbox, fo... — committed to arvados/arvados by ldipenti 4 years ago
Hey team, we’ve also hit this problem as we have a few cases where we reference constants in our initialisers and our factories (which are being loaded as a part of
after_initialize
). @bwillis – how did you end up going about avoiding loading factories inafter_initialize
? @aried3r – have you found a solution for yourif Product.table_exists?
example? Thanks in advance!Should quickly add we’ve managed to solve our issue by guarding the areas where classes were being loaded with
ActiveRecord::Base.connected?
– we had a few guards ofActiveRecord::Base.connection.data_source_exists?("model")
but these seemed to no longer behave the way they did in Rails 4.x (we have only recently upgraded to 5.2).I think the question here should be whether the use of models is not allowed in
after_initialize
blocks. With this change it means that allafter_initialize
blocks should not contain any code that attempts to connect to the database otherwise,rake db:create
will not work.Then loading it where we needed it explicitly, which, for us, was in our spec helper: