Open benlangfeld opened 5 years ago
For now it does not tackle any configuration changes (we can hash that out in future PRs).
@benlangfeld Have you tried using the establish_connection
method to pick the database to connect to in the base records instead of the connects_to
method? This is what @eileencodes does in her example application. Here database.yml looks like this, and her base records looks like this and this.
1) The comment about configurations was specifically regarding DHH wanting more levels than 2 or 3 tier configs. Configurations work fine otherwise.
2) The demo app that @terryfinn is super old and not correct.
3) I don't know if the way you're using connects_to
can work like that. That connects_to
is per model so that the connection_specification_name
can be applied correctly. You can't put it in ApplicationRecord (every single connection would then get ApplicationRecord as it's connection_specification_name and they'd each clobber each other). You need a model per database type like @terryfinn linked to in https://github.com/eileencodes/multiple_databases_demo/blob/master/app/models/animals_base.rb
@terryfinn Yes, I did try that, with the same result.
@eileencodes Thanks for commenting! We do indeed have a different base class for each database type, being an Airlines::ApplicationRecord
and a Destinations::ApplicationRecord
, where each live in separate engines. Would that not be enough for the specification name not to collide?
The intent here is for the set of models/tables in each engine (which are combined into a single application) to use the same database (2 engines mounted in an app therefore using two databases). For context, this is an exploration of how Rails 6' multi-database support might work with Component Based Rails Apps. Our real-world use case is of course significantly more complex.
Thanks for commenting! We do indeed have a different base class for each database type, being an Airlines::ApplicationRecord and a Destinations::ApplicationRecord, where each live in separate engines. Would that not be enough for the specification name not to collide?
I can't tell from your database config but it looks like maybe you're implementing sharding? We haven't implemented that at all yet, we just have basic connection switching for telling the code to go from a primary to a replica and back again:
The problem is here:
All of the connections you create here will have Destinations::ApplicationRecord
as the specification name. The last one will win so you'll only have a writing and reading connection for the last one in the db_name list.
Yes, the intent is sharding. I guess I mis-understood what had been implemented so far. Is support for sharding on the roadmap for Rails 6.0?
As for the "last one wins", we're not actually looping there so I don't think that's a concern.
Thank you again for your help, super-hero style!
As for the "last one wins", we're not actually looping there so I don't think that's a concern.
Ah right, looked like you were for some reason. Long day! 😄
Is support for sharding on the roadmap for Rails 6.0?
Yea we plan on implementing it for 6. There are folks on the core team who use sharding in production that are interested in seeing it go in. We don't use sharding at GH so I'm focusing on getting other stuff working.
@benlangfeld I was able to modify your branch and was able to get the models connecting to the database. I made three changes:
db_name_file
under the Rails.root
. This file only seemed to be present in the engines dummy app folder. Not sure what the use was of that, but it was not available in the context I was running things form.ApplicationRecord
classes to use establish_connection
instead of connects_to
.config/database.yml
to enumerate the configurations for the different components databases. module Airlines
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
- db_name_file = File.join(Rails.root, "db/name")
- if File.exists?(db_name_file)
- db_name = File.read(db_name_file).chomp
- establish_connection db_name
- end
+ establish_connection :airline
end
end
development:
primary:
<<: *default
database: <%= db_name %>_development
- <%= db_name %>:
+ airline:
<<: *default
- database: <%= db_name %>_development
+ database: airline_development
And when you run the dummy app, does that work, or only the umbrella? It’s important that it works in the dummy app so that we can run tests.
The “routes” component is intended to depend on the other two and implement a join table, demonstrating how tests would run concurrently with such dependencies, where the routes component would need 3 databases separate from the databases used by each of its dependencies.