Devise
User Model
Database Migration
Main/Replica Architecture
Ruby on Rails

Creating and migrating a devise-driven User model in a main/replica context

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

When developing applications with high availability and scalability in mind, it becomes necessary to consider architectures beyond a single database. One common setup is having a main database (also known as primary or master) and one or more replica (slave) databases. This article will guide you through creating and migrating a User model in a Ruby on Rails application using the Devise gem in a main/replica database context.

Understanding Main/Replica Architecture

In a main/replica setup, the main database handles all write operations, while the replica handles read operations. This architecture helps in load distribution and increases read throughput, which is especially beneficial for read-heavy applications.

Setting Up Devise

Devise is a flexible authentication solution for Rails based on Warden. It provides a comprehensive suite of features and is easy to integrate and customize. To begin, add Devise to your Gemfile:

ruby
gem 'devise'

Run bundle install to install the gem. After that, you need to set up Devise in your Rails application:

bash
rails generate devise:install

This command creates the necessary configuration files and initializer under config/initializers/devise.rb.

Creating the User Model

Now, generate your User model using Devise:

bash
rails generate devise User

This command constructs the model with default modules such as database authenticatable, registerable, recoverable, rememberable, trackable, and confirmable. Also, it automatically creates a migration file for the users table.

Configuring Database.yml

Your database.yml needs to reflect your main/replica setup. For instance:

yaml
1production:
2  primary:
3    <<: *default
4    database: app_production
5    username: app
6    password: <%= ENV['APP_DATABASE_PASSWORD'] %>
7    host: primary.db.example.com
8
9  replica:
10    <<: *default
11    database: app_production
12    username: app
13    password: <%= ENV['APP_DATABASE_PASSWORD'] %>
14    host: replica.db.example.com
15    readonly: true

Implementing Read/Write Split

To implement read/write split in Rails, you can use the active_record_slave gem or similar plugins which provide a mechanism to direct read queries to the replica. However, from Rails 6 onwards, you can also utilize the built-in Role and Sharding support to direct traffic to the appropriate database:

ruby
class ApplicationRecord < ActiveRecord::Base
  connects_to database: { writing: :primary, reading: :replica }
end

Handling Migrations

Migrations should always be run against the main database because the replica is typically read-only and receives updates via replication from the main database. Ensure that your migration scripts and Rails environment are configured to connect to the primary database when performing these migrations.

bash
RAILS_ENV=production bin/rails db:migrate

This command ensures that Rails connects to the primary database as specified in the database.yml.

Summary Table of Key Components

ComponentDescriptionRails Command / Code
Devise SetupAdding user authentication system to Rails.rails generate devise:install
User ModelCreating the user model using Devise.rails generate devise User
Database ConfigSetting up YAML configuration for main/replica.Edit config/database.yml
Read/Write SplitConfiguring application to handle database roles.connects_to database: &#123;writing: :primary, reading: :replica&#125;
MigrationsRunning migrations on the main database.RAILS_ENV=production bin/rails db:migrate

Additional Considerations

  • Error Handling: Implement robust error handling to address any connection issues with the replica.
  • Monitoring and Failover: Set up monitoring for the databases and have a plan for failover in case the primary database goes down.

By following these steps, you can effectively set up and manage a Devise-driven User model in a main/replica database architecture, allowing your Rails application to scale efficiently while maintaining robust data integrity and availability.


Course illustration
Course illustration

All Rights Reserved.