DEV Community

Cover image for Simple Multitenancy in Rails
Ritikesh
Ritikesh

Posted on • Updated on

Simple Multitenancy in Rails

In this post, I would like to share a few snippets on how to use concerns in Rails to share some basic reusable multi-tenant patterns.


Multi-tenancy is a common problem to solve in todays cloud-first world. The core part to a Multitenant Architecture is a "Tenant". A Tenant can be anything - a Store(Shopify), an Account(org using a SaaS product) or even a User - and typically, has data partitioned in associated tables or databases.
For heavy multi-tenant feature-set or functionality, there are many community driven gems available. You can find the complete list on ruby-toolbox. For smaller projects or learning exercises, I would rather recommend building the system on your own. It gives you clarity and greater understanding of the framework itself.
Below, is a simple concern that can get you started on making your apps multi-tenant by design. All models that include the below concern will be multi-tenant by default.


This bring me to the second pattern. One might think what could Tenant.current mean. In any application involving tenants or users, you are most likely to set a global context of the user who is responsible for the current execution - most likely the currently signed in user. 
Typically for rails developers, this involves setting and accessing the current_user in the Thread context like Thread.current[current_user]. If you were to extend this behaviour to more actors or objects like a tenant, this can be abstracted into a useful pattern and reuse the concern.

Upon including the above concern in a model, you get 3 methods by default. An instance level make_current method to set the loaded object as current in context. Next are class level current and reset_current methods. The former returns the currently set object and the latter resets it.


The creator pattern which tags the current user as the creator of the object being created.

Typical use-cases of this is to map entity creation with users for auditing or logging purposes.

Top comments (2)

Collapse
 
rhs0112 profile image
rhs0112

Thanks for posting this. Could you also provide on example (of a model) that uses this concern to ensure multi tenancy?

Collapse
 
ritikesh profile image
Ritikesh

Hey, Thanks for reading. You can easily include the concerns and use them as you go. For eg.)

If you have a user class that you want to make current'able, add the following code:

# app/models/user.rb

class User < ActiveRecord::Base
  include ActsAsCurrent
end

# app/helpers/application_helper.rb

class ApplicationHelper
  def current_user
    return User.current if User.current
    User.find(session[:id]).make_current
  end
end

# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base

  after_filter :reset_current_user

  private
  def reset_current_user
    User.reset_current
  end
end