citusdata/activerecord-multi-tenant

Name: activerecord-multi-tenant

Owner: Citus Data

Description: Rails/ActiveRecord support for distributed multi-tenant databases like Postgres+Citus

Created: 2016-09-10 00:05:34.0

Updated: 2018-05-24 12:26:21.0

Pushed: 2018-05-03 00:44:56.0

Homepage:

Size: 163

Language: Ruby

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

activerecord-multi-tenant

Introduction Post: https://www.citusdata.com/blog/2017/01/05/easily-scale-out-multi-tenant-apps/

ActiveRecord/Rails integration for multi-tenant databases, in particular the open-source Citus extension for PostgreSQL.

Enables easy scale-out by adding the tenant context to your queries, enabling the database (e.g. Citus) to efficiently route queries to the right database node.

Installation

Add the following to your Gemfile:

'activerecord-multi-tenant'
Supported Rails versions

All Ruby on Rails versions starting with 4.0 or newer are supported.

This gem only supports ActiveRecord (the Rails default ORM), and not alternative ORMs like Sequel.

Usage

It is required that you add multi_tenant definitions to your model in order to have full support for Citus, in particular when updating records.

In the example of an analytics application, sharding on customer_id, annotate your models like this:

s PageView < ActiveRecord::Base
lti_tenant :customer
longs_to :site

...


s Site < ActiveRecord::Base
lti_tenant :customer
s_many :page_views

...

and then wrap all code that runs queries/modifications in blocks like this:

omer = Customer.find(session[:current_customer_id])
.
iTenant.with(customer) do
te = Site.find(params[:site_id])
te.update! last_accessed_at: Time.now
te.page_views.count

Inside controllers you can use a before_action together with set_current_tenant, to set the tenant for the current request:

s ApplicationController < ActionController::Base
t_current_tenant_through_filter # Required to opt into this behavior
fore_action :set_customer_as_tenant

f set_customer_as_tenant
customer = Customer.find(session[:current_customer_id])
set_current_tenant(customer)
d

Rolling out activerecord-multi-tenant for your application (write-only mode)

The library relies on tenant_id to be present and NOT NULL for all rows. However, its often useful to have the library set the tenant_id for new records, and then backfilling tenant_id for existing records as a background task.

To support this, there is a write-only mode, in which tenant_id is not included in queries, but only set for new records. Include the following in an initializer to enable it:

iTenant.enable_write_only_mode

Once you are ready to enforce tenancy, make your tenant_id column NOT NULL and simply remove that line.

Frequently Asked Questions
Credits

This gem was initially based on acts_as_tenant, and still shares some code. We thank the authors for their efforts.

License

Licensed under the MIT license
Copyright (c) 2017, Citus Data Inc.


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.