Rails 6.1 creates abstract classes in multiple database mode

Akhil Gautam

By Akhil Gautam

on August 4, 2020

This blog is part of our  Rails 6.1 series.

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

Rails 6.1

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.

Stay up to date with our blogs. Sign up for our newsletter.

We write about Ruby on Rails, ReactJS, React Native, remote work,open source, engineering & design.