Skills

Multi Tenant Setup

Implements URL-based multi-tenancy with account scoping, membership patterns, and data...

Install

npx skills add ThibautBaissac/rails_ai_agents --skill multi-tenant-setup -g -a claude-code -y
Category
Engineering
Updated
5mo ago
License
MIT
Context cost
Mediumabout 2,508 tokens
Runs scripts
No, instructions only

What it does

Implements URL-based multi-tenancy with account scoping, membership patterns, and data isolation following 37signals patterns. Use when setting up multi-tenant architecture, account isolation, membership management, or when user mentions multi-tenancy, accounts, or tenant separation. WHEN NOT: For basic model setup without tenancy (use model-patterns), for auth/session setup (use auth-setup).

Multi-Tenant Setup

Philosophy: URL-Based Multi-Tenancy, Not Subdomain or Schema

  • URL-based: app.myapp.com/123/boards/456 (account_id in path)
  • account_id on every table (no foreign key constraints)
  • Current.account set from URL params for all requests
  • All queries scoped through Current.account
  • UUIDs everywhere (prevents enumeration attacks)
  • No default scopes (explicit scoping preferred)
  • No Apartment gem, no subdomain routing, no schema separation

Project Knowledge

Stack: URL-based multi-tenancy (/accounts/:account_id/...), Current attributes for account/user context, UUIDs for all primary keys, single database with single schema.

Auth: Custom passwordless with Current.user, users can belong to multiple accounts, account membership controls access.

Commands:

rails generate model Account name:string
rails generate model Membership user:references account:references role:integer
rails generate migration AddAccountToCards account:references

Pattern 1: Account Model and Memberships

See @references/membership-patterns.md for full details.

# app/models/account.rb
class Account < ApplicationRecord
  has_many :memberships, dependent: :destroy
  has_many :users, through: :memberships

  has_many :boards, dependent: :destroy
  has_many :cards, dependent: :destroy

  validates :name, presence: true, length: { maximum: 100 }

  def member?(user)
    users.exists?(user.id)
  end

  def add_member(user, role: :member)
    memberships.find_or_create_by!(user: user) do |membership|
      membership.role = role
    end
  end

  def owner
    memberships.owner.first&.user
  end
end

# app/models/membership.rb
class Membership < ApplicationRecord
  belongs_to :user
  belongs_to :account

  enum :role, { member: 0, admin: 1, owner: 2 }

  validates :user_id, uniqueness: { scope: :account_id }
  validates :role, presence: true

  scope :active, -> { where(active: true) }
end
Read the whole SKILL.md on GitHub

More in Engineering