Skip to content

Multiple databases v2#454

Open
calebhearth wants to merge 2 commits intomainfrom
multidb-and-views-paths
Open

Multiple databases v2#454
calebhearth wants to merge 2 commits intomainfrom
multidb-and-views-paths

Conversation

@calebhearth
Copy link
Copy Markdown
Contributor

Add quite a bit more testing to the multiple databases feature, especially
around configuraiton, definition, and statement routing. Introduce a new
FakeAdapter class to let us test against a non-Postgres adapter without having a
dependency on any of the various actual adapters out there (we love you, but we
don't want a cyclic dependency!)

  • Rework the new README changes to somewhat closer match the cheeky style of the
    original.
  • Fix array handling for migrations_paths. Rails lets us define a
    :migrations_paths key that can be an array or a string in database.yml,
    and we previously ignored the possibility of that being an array. New
    functionality matches what Rails does.

Introduce configurable view paths! I'm hopeful that a lot of folks will be happy
with this. You can configure this with views_paths in database.yml and it
should default similarly to how migrations do to db/<database_name>_views/ for
non-default databases.

Fix: #291
Fix: #380
Fix: #261
Resolves: #402
Closes: #451

dnamsons and others added 2 commits November 14, 2025 14:28
Add quite a bit more testing to the multiple databases feature, especially
around configuraiton, definition, and statement routing. Introduce a new
FakeAdapter class to let us test against a non-Postgres adapter without having a
dependency on any of the various actual adapters out there (we love you, but we
don't want a cyclic dependency!)

- Rework the new README changes to somewhat closer match the cheeky style of the
  original.
- Fix array handling for migrations_paths. Rails lets us define a
  `:migrations_paths` key that can be an array or a string in `database.yml`,
  and we previously ignored the possibility of that being an array. New
  functionality matches what Rails does.

Introduce configurable view paths! I'm hopeful that a lot of folks will be happy
with this. You can configure this with `views_paths` in `database.yml` and it
should default similarly to how migrations do to `db/<database_name>_views/` for
non-default databases.

Fix: #291
Fix: #380
Fix: #261
@calebhearth
Copy link
Copy Markdown
Contributor Author

@dnamsons @leoplct @joshfester Would you like to give this a shot for the multiple dbs and/or adapters implementation?

@sullerandras @smdern @coding-chimp @MarcReniu @tomasc @huarmenta @vladimirtemnikov @nathanpalmer @jdno @shageman @hlascelles and probably others, this may also get us closer to some of the various Engines and configurable db/views paths needs so I'd love to get input on that as well!

@robotfelix
Copy link
Copy Markdown

@calebhearth @dnamsons Great work on this. Supporting multiple databases (prior to any built-in Rails support) was the primary reason we originally forked the gem, and it would be great to see this merged and get back on main.

I've done a bit of local testing of this, and everything around migrations (rollbacks, view paths) seems to work great.

scenic/README.md

Lines 280 to 289 in bf8c8aa

If you're using different adapters for different databases (say, Postgres for
your primary database and MySQL for analytics), you can configure them in an
initializer:
```ruby
# config/initializers/scenic.rb
Scenic.configure do |config|
config.databases[:secondary] = Scenic::Adapters::Postgres.new(SecondaryRecord)
end
```

One thing I've encountered is that the README updates seem to suggest that adding explicit configuration is only necessary when using multiple adapters, which seems to be true for migrations, but not 100% true overall.

Without this additional configuration then Scenic.database(:secondary).refresh_materialized_view('my_materialized_view') executes the SQL against the primary database, which seems like an easy-to-miss footgun. Digging into it, this seems to be because the default adapter uses a connection from ActiveRecord::Base. The safest path might be to suggest always adding the extra initializer and to make Scenic.database(:secondary) error if none has been configured.

@robotfelix
Copy link
Copy Markdown

https://github.com/rails/rails/blob/0e53474dd25bb06cc87c07a75ffec49d3490152c/activerecord/lib/active_record/database_configurations.rb#L138-L149

The only other thing I'd note is that there is a subtle distinction between "default" and "primary". Rails seems to mostly use "primary" when referring to the main database in multiple-database setups, but also seems to use "default" within its code.

I'm not confident to say if any of the new code here is using "default" when it should be using "primary", but it's worth noting that in a slightly pathological case like the below, I understand that :primary takes precedence over :default as the default/automatic ActiveRecord::Base database.

development:
  default:
    adapter: postgresql
    url: ...
  primary:
    adapter: postgresql
    url: ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants