There are many use cases for achieving multitenancy in a Rails application. Two of the best gems to use for this purpose are apartment and acts_as_tenant. Both work well and are commonly used. Here are some tips for using acts_as_tenant
along with Devise, the most common user authentication gem, to create a multitenant Rails application
Setting up Devise
Add devise
gem to your Gemfile
and run bundle install
.
1
gem "devise"
Run the following commands in your terminal:
1
2
rails generate devise:install
rails generate devise User
Scaffolding
Create a scaffold for which we want to achieve multitenancy.
1
rails generate scaffold Project name
Creating models and necessary migrations
Run the following migrations in your terminal:
1
2
rails generate model Account user:references
rails generate migration add_account_to_projects
Add this in your add_account_to_projects
migration:
1
2
3
4
5
6
class AddAccountToProjects < ActiveRecord::Migration[6.0]
def change
add_column :projects, :account_id, :integer
add_index :projects, :account_id
end
end
Run rails db:migrate
.
Setting up acts_as_tenant
Now add acts_as_tenant gem in your Gemfile and run bundle install
.
1
gem "acts_as_tenant"
Add this line to your project.rb
:
1
2
3
class Project < ApplicationRecord
acts_as_tenant :account
end
And the following lines to user.rb
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
has_one :account
before_validation :set_account
def set_account
self.build_account
end
end
And this to account.rb
:
1
2
3
class Account < ApplicationRecord
belongs_to :user
end
Setting current tenant in the application controller
Now in the application_controller.rb
file, put this code:
1
2
3
4
5
6
7
8
9
10
11
class ApplicationController < ActionController::Base
before_action :authenticate_user!
set_current_tenant_through_filter
before_action :set_current_account
def set_current_account
return unless current_user.present?
current_account = current_user.account
ActsAsTenant.current_tenant = current_account
end
end
That’s it. You have configured acts_as_tenant
in your Rails application and it will set tenant to the current user’s account for every query to Project model to refer to.