Set up a basic multi-tenant architecture in Rails 7 - 1
Tags: multitenancy, rails, ruby, beginners
Published: 2023-01-30 17:18:39

## Basic understanding of multi tenancy in rails

Multi-tenancy in Rails refers to the capability of a single instance of a Rails application to serve multiple, isolated tenants (i.e. separate customers or organizations) using the same codebase and infrastructure. Each tenant has its own set of data, which is stored in separate databases or schemas, and they cannot access or interfere with each other's data.

A multi-tenant Rails application is typically designed to allow tenants to customize certain aspects of their instance, such as branding, themes, and feature configurations. To implement multi-tenancy in Rails, you can use a gem such as Apartment to manage multiple databases or schemas and switch between them based on the tenant identifier.

In a multi-tenant Rails application, tenants are typically identified by a unique identifier such as a subdomain or a path in the URL. The tenant identifier is used to switch to the appropriate database or schema for that tenant, and all subsequent requests for that tenant are processed using the data from that schema.

Multi-tenancy has several benefits, including cost savings, improved scalability, and enhanced security. By running multiple tenants on a single instance of an application, you can reduce the costs associated with hosting and maintaining separate instances for each tenant. Multi-tenancy also allows you to scale your application more easily, as you can add new tenants without having to provision new hardware or infrastructure. Additionally, multi-tenancy helps to improve security by isolating data between tenants, reducing the risk of data breaches and ensuring that each tenant's data is secure.

**To set up a basic multi-tenant architecture in Rails 7, you can follow these steps:**

Add the Apartment gem to your Gemfile:
`gem 'apartment'`

Run bundle install.

Create a Tenant model:
`rails g model Tenant name subdomain`

Add the tenant identifier column to each table:
`rails g migration AddTenantIdToUsers tenant_id:integer`

Configure Apartment in an initializer:
```ruby
Apartment.configure do |config|
  config.excluded_models = %w[Tenant]
  config.tenant_names = lambda { Tenant.pluck(:subdomain) }
end
```

Use the tenant identifier to switch between schemas in your application:

```ruby
class ApplicationController < ActionController::Base
  before_action :set_tenant

  private

  def set_tenant
    tenant = Tenant.find_by(subdomain: request.subdomain)
    Apartment::Tenant.switch(tenant.subdomain) if tenant
  end
end
```

With these steps, you have set up a basic multi-tenant architecture in Rails 7 that allows you to run multiple instances of your application, each with its own set of data, on a single codebase and infrastructure.

**We can also create with Rails API**

Create API endpoints for tenants:

```ruby
class TenantsController < ApplicationController
  def create
    tenant = Tenant.create!(tenant_params)
    Apartment::Tenant.create(tenant.subdomain)
    render json: { message: 'Tenant created successfully' }, status: :created
  end

  private

  def tenant_params
    params.require(:tenant).permit(:name, :subdomain)
  end
end
```
With these steps, you have set up a basic multi-tenant architecture in a Rails API application that allows you to serve multiple tenants with a single codebase and infrastructure, each with its own set of data. The tenant identifier (subdomain) is used to switch to the appropriate database or schema for that tenant, and all subsequent requests for that tenant are processed using the data from that schema.

**Create sign up and login pages for tenants**

```ruby
class TenantsController < ApplicationController
  def new
    @tenant = Tenant.new
  end

  def create
    tenant = Tenant.create!(tenant_params)
    Apartment::Tenant.create(tenant.subdomain)
    redirect_to root_url(subdomain: tenant.subdomain)
  end

  private

  def tenant_params
    params.require(:tenant).permit(:name, :subdomain)
  end
end
```



**Multi-tenant architecture can be used in various applications in Rails, including:**

SaaS (Software as a Service) applications: Multi-tenancy is a common design pattern for SaaS applications, as it allows you to serve multiple customers or organizations with a single instance of the application.

Marketplace applications: Multi-tenancy can be used to support multiple vendors or sellers in a marketplace, where each vendor has its own set of data and cannot access or interfere with the data of other vendors.

Enterprise applications: Multi-tenancy can be used in enterprise applications to support multiple departments or subsidiaries, each with its own data and configurations.

Educational applications: Multi-tenancy can be used in educational applications to support multiple schools or institutions, each with its own data and configurations.

Healthcare applications: Multi-tenancy can be used in healthcare applications to support multiple healthcare providers, each with its own set of data and configurations.

These are just a few examples of where multi-tenancy can be used in Rails. The key advantage of multi-tenancy is that it allows you to serve multiple customers or organizations with a single instance of the application, reducing the costs and complexity associated with maintaining separate instances for each customer.


## Here is a detailed code example for a multi-tenant healthcare application in Rails:

Add the Apartment gem to your Gemfile:
`gem 'apartment'`

Run bundle install.

Create a Hospital model:
`rails g model Hospital name`

Add the tenant identifier column to each table:
`rails g migration AddHospitalIdToPatients hospital_id:integer`

Configure Apartment in an initializer:

```ruby
Apartment.configure do |config|
  config.excluded_models = %w[Hospital]
  config.tenant_names = lambda { Hospital.pluck(:name) }
end
```

Use the tenant identifier to switch between schemas in your controllers:

```ruby
class ApplicationController < ActionController::Base
  before_action :set_tenant

  private

  def set_tenant
    hospital = Hospital.find_by(name: request.subdomain)
    Apartment::Tenant.switch(hospital.name) if hospital
  end
end
```

Create sign up and login pages for hospitals:

```ruby
class HospitalsController < ApplicationController
  def new
    @hospital = Hospital.new
  end

  def create
    hospital = Hospital.create!(hospital_params)
    Apartment::Tenant.create(hospital.name)
    redirect_to root_url(subdomain: hospital.name)
  end

  private

  def hospital_params
    params.require(:hospital).permit(:name)
  end
end
```

Create the Patients table for each new hospital that signs up:

```ruby
class CreatePatients < ActiveRecord::Migration[6.0]
  def change
    create_table :patients do |t|
      t.string :first_name
      t.string :last_name
      t.string :email
      t.integer :hospital_id
      t.timestamps
    end
  end
end
```
Create the Appointments table for each new hospital that signs up:

```ruby
class CreateAppointments < ActiveRecord::Migration[6.0]
  def change
    create_table :appointments do |t|
      t.datetime :date_time
      t.integer :patient_id
      t.integer :hospital_id
      t.timestamps
    end
  end
end
```

With these steps, you have set up a basic multi-tenant healthcare application in Rails that allows multiple hospitals to sign up and use the application, each with its own subdomain and data

The tenant identifier (subdomain) is used to switch to the appropriate database or schema for that hospital, and all subsequent requests for that hospital are processed using the data from that schema. When a new hospital signs up, the Patients and Appointments tables are created for that hospital within its own schema, and all data for that hospital is stored and processed within that schema.