We write about Ruby on Rails, React.js, React Native, remote work, open source, engineering and design.
Rails
started supporting
multiple databases
from Rails 6.0.
To use a specific database,
we can specify the
database connection
in the model
using connects_to
.
In the following case we want Person
model to connect to crm
database.
1
2class Person < ApplicationRecord
3connects_to database: { writing: :crm }
4end
5
As the application grows,
more and more
models start sharing
the same database.
Now a lot of models may
contain connects_to
call
to the same database.
1class Person < ApplicationRecord
2connects_to database: { writing: :crm }
3end
4
5class Order < ApplicationRecord
6connects_to database: { writing: :crm }
7end
8
9class Sale < ApplicationRecord
10connects_to database: { writing: :crm }
11end
In order to avoid the duplication, we can create an abstract class connecting to a database and manually inherit all other models from that class. This could look like this.
1class CrmRecord < ApplicationRecord
2self.abstract_class = true
3
4connects_to database: { writing: :crm }
5end
6
7class Person < CrmRecord
8end
9
10class Order < CrmRecord
11end
12
13class Sale < CrmRecord
14end
Before Rails 6.1 we had no choice but to
create that abstract class manually.
Rails 6.1 allows us to generate an abstract class when we are generating a model using scaffold
.
1$ rails g scaffold Person name:string --database=crm
It creates
an abstract class
with the
database's name
appended with Record
.
The generated model
automatically inherits
from
the new abstract class.
1
2# app/models/users_record.rb
3
4class CrmRecord < ApplicationRecord
5self.abstract_class = true
6
7connects_to database: { writing: :crm }
8end
9
10# app/models/admin.rb
11
12class Person < CrmRecord
13end
If the
abstract class
already exists,
it is not
created again.
We can also
use an existing
class as the abstract class
by passing
parent
option to
the scaffold command.
1$ rails g scaffold Customer name:string --database=crm --parent=PrimaryRecord
This skips
generating CrmRecord
class
as we have
specified Rails
to use
PrimaryRecord
abstract class
as its parent.
Check out the pull request for more details on this.