Closed 2called-chaos closed 6 months ago
This is expected.
Prior to 7.1, if you had multiple databases in an environment (e.g. shard_1
, shard_2
), and you ran bin/rake -T
, you wouldn't see tasks such as rake db:create:shard_1
because the environment was never loaded therefore database.yml
was never loaded.
Rails 7.1 gets around this by loading database.yml
with a fake/dummy app config (not the real environment) and when you run bin/rake -T
you'll see:
rake db:create:shard_1 # Create shard_1 database for current environment
rake db:create:shard_2 # Create shard_2 database for current environment
When you actually run a task like db:create
in Rails 7.1, it'll load database.yml
with the dummy app config, load the actual app, and then load database.yml
again with the non-dummy/real app config.
So no, nothing breaks.
Alright so it doesn't matter if the dummy does not get proper credentials? Not sure what the best course of action is for us but it does break if your initializer defines something your yml attempts to use like a config object (that doesn't ignore missing keys).
Like I can use Rails.application.credentials
but where would I initialize my custom config if not in an initializer, even environment.rb is too late?
That is strange. The dummy config thing should not have changed the order. Did you find the commit that changed this behavior?
@rafaelfranca it's not that the order has changed, it's that the ERB is no longer being stripped out (on initial database.yml load). Here's the commit that changes it: https://github.com/rails/rails/pull/46134
I just wanted to confirm the change that introduced the change of behavior.
@2called-chaos if you custom configuration is inside Rails.application.config
things would just work. Closing since this isn't an issue.
This is expected.
Prior to 7.1, if you had multiple databases in an environment (e.g.
shard_1
,shard_2
), and you ranbin/rake -T
, you wouldn't see tasks such asrake db:create:shard_1
because the environment was never loaded thereforedatabase.yml
was never loaded.Rails 7.1 gets around this by loading
database.yml
with a fake/dummy app config (not the real environment) and when you runbin/rake -T
you'll see:rake db:create:shard_1 # Create shard_1 database for current environment rake db:create:shard_2 # Create shard_2 database for current environment
When you actually run a task like
db:create
in Rails 7.1, it'll loaddatabase.yml
with the dummy app config, load the actual app, and then loaddatabase.yml
again with the non-dummy/real app config.So no, nothing breaks.
This was totally wrong. I understand it now. Here's the proper explanation:
Let's say you have a constant in an initializer named FOO
and you use it as a value in database.yml. Prior to Rails 7.1, this ERB value would get replaced with an empty string. So on the initial database.yml load, you won't get the "uninitialized constant" error.
In Rails 7.1, the ERB values in database.yml are not replaced, so when it is initially loaded, you'll get NameError: uninitialized constant FOO (NameError)
. The parsing of database.yml is dependent on the interface of Rails config, so it makes sense to use it for custom config values. An alternative would be to place your code after Bundler.require
in application.rb
.
Steps to reproduce
<% puts "database.yml" %>
puts "initializer"
rails db:migrate
orrails db:create
on <7.1 (e.g. 7.0.8.1) and >= 7.1.0Expected behavior (as was the case <7.1)
Initializers run before database.yml gets interpreted by ERB.
Actual behavior (since 7.1)
Initializers now run after database.yml has been interpreted by ERB
System configuration
Rails version: 7.0.8.1, 7.1.0, 7.1.3.2
Ruby version: 3.3.0
Not sure if this is intended but as far as I can tell not documented. This obviously breaks if you attempt to use config data sourced and/or configured by an initializer in your database.yml.