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- Repository
- ThibautBaissac/rails_ai_agents671
- 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_idon every table (no foreign key constraints)Current.accountset 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
