Rails has introduced support for multiple databases in application.
Rails now provides a method connects_to which we need to specify at the
model level and mention the databases as shown below:
class User < ApplicationRecord
connects_to database: { writing: :primary, reading: :replica }
endAs specified in the connects_to block above, all the update and
insert queries will be executed on the primary database and select
queries on replica.
connects_to method must be specified in the common base class,
let’s say ApplicationRecord and this can be inherited by other models
as needed. Database clients have a limit on the number of open
connections and hence we need to specify connects_to in a single model
base class. If this is not done, the number of open connections will add
up since Rails uses the model class name for the database connection.
The database.yml for the above configuration may look like as below:
development:
primary:
database: my_primary_database
user: root
adapter: mysql
replica:
database: my_primary_database
user: root_readonly
adapter: mysql
replica: trueWe need to specify replica: true in our replica configuration because
Rails need a way to identify which one is a replica and which one is
primary. The primary and replica database name will be the same,
but the user permissions should be different.
Outside the model, we might want to connect to a completely different database.
Let’s say for the above example, if we have another archive database for
storing deactivated user, we can use Rails connected_to method as
shown below:
ActiveRecord::Base.connected_to(database: :archive_db) do
User.fetch_all_deactivated
end:archive_db is the database key in our database.yml config file.
We can connect to a different database by using the role parameter too.
ActiveRecord::Base.connected_to(role: :reading) do
# finds user from replica connected to ApplicationRecord
User.first
endBy default the :writing role will be used since all connections must be
assigned a role. If you would like to use a different role you can pass
a hash to the database:
ActiveRecord::Base.connected_to(database: { readonly_slow: :replica }) do
# runs a long query while connected to the +replica+ using the readonly_slow role.
User.run_a_huge_query
endRails by default expect database roles to be writing and reading for the primary
and replica respectively. If we want to have our roles, we need to create them
and specify them in our application config.
config.active_record.writing_role = :writes
config.active_record.reading_role = :readonlyNOTE:
- When using the database key, a new connection will be established every time. It is not recommended to use this outside of one-time scripts.
