### Installation and Setup
Source: https://github.com/rameerez/organizations/blob/main/README.md
Install the gem, run migrations, and mount the engine in your Rails routes to enable the organization management system.
```bash
bundle install
rails g organizations:install
rails db:migrate
```
```ruby
# config/routes.rb
mount Organizations::Engine => '/'
```
--------------------------------
### Configure Test Helpers
Source: https://context7.com/rameerez/organizations/llms.txt
Setup instructions for including organization test helpers in ActiveSupport::TestCase and example usage for authentication and organization context.
```ruby
require "organizations/test_helpers"
class ActiveSupport::TestCase
include Organizations::TestHelpers
end
test "admin can invite members" do
user = users(:admin)
org = organizations(:acme)
sign_in_as_organization_member(user, org, role: :admin)
set_current_organization(org)
assert user.is_admin_of?(org)
assert user.has_organization_permission_to?(:invite_members)
end
```
--------------------------------
### Create Organizations
Source: https://context7.com/rameerez/organizations/llms.txt
Provides examples of how users can create new organizations, either with just a name or with additional attributes. It also demonstrates how to handle the `OrganizationLimitReached` exception.
```ruby
# Create an organization with just a name
org = current_user.create_organization!("Acme Corp")
# User automatically becomes the owner
```
```ruby
# Create with additional attributes
org = current_user.create_organization!(
name: "Acme Corp",
support_email: "support@acme.com"
)
```
```ruby
# Check organization limits
begin
current_user.create_organization!("Another Org")
rescue Organizations::Models::Concerns::HasOrganizations::OrganizationLimitReached => e
puts e.message # "Maximum number of organizations (5) reached"
end
```
--------------------------------
### Install Organizations Gem
Source: https://context7.com/rameerez/organizations/llms.txt
Instructions for adding the Organizations gem to your Rails application's Gemfile, installing it, and running the necessary generators and migrations.
```ruby
# Gemfile
gem "organizations"
```
```bash
bundle install
rails g organizations:install
rails db:migrate
```
--------------------------------
### Development Setup and Testing (Bash)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Provides the bash commands necessary to clone the organizations gem repository, set up the development environment, and run the test suite.
```bash
git clone https://github.com/rameerez/organizations
cd organizations
bin/setup
bundle exec rake test
```
--------------------------------
### Optimize Queries and Permissions
Source: https://github.com/rameerez/organizations/blob/main/README.md
Provides examples for eager loading associations to prevent N+1 queries and explains that permission checks are performed in-memory.
```ruby
# Eager loading to avoid N+1
org.memberships.includes(:user).each do |membership|
membership.user.name
end
# Permission checks (in-memory, no DB query)
user.has_organization_permission_to?(:invite_members)
org.memberships.includes(:user).each do |m|
m.has_permission_to?(:invite_members)
end
```
--------------------------------
### Configure User Model for Organizations
Source: https://context7.com/rameerez/organizations/llms.txt
Demonstrates how to enable organization support on your User model using the `has_organizations` macro. Includes examples with and without configuration options like `max_organizations`, `create_personal_org`, and `require_organization`.
```ruby
# app/models/user.rb
class User < ApplicationRecord
has_organizations
end
```
```ruby
# With configuration options
class User < ApplicationRecord
has_organizations do
max_organizations 5 # Limit how many orgs a user can own (nil = unlimited)
create_personal_org true # Auto-create org on signup (default: false)
require_organization true # Require users to have at least one org (default: false)
end
end
```
--------------------------------
### Use Rails Fixtures for Organizations and Memberships
Source: https://github.com/rameerez/organizations/blob/main/README.md
Configure Rails fixtures to define organizations and their memberships. This allows for easy setup of test data, ensuring consistent states for your tests.
```yaml
# test/fixtures/organizations.yml
acme:
name: Acme Corp
# test/fixtures/memberships.yml
john_at_acme:
user: john
organization: acme
role: admin
```
--------------------------------
### Handle Row-Level Locking for Data Consistency in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Examples of using row-level locking (SELECT FOR UPDATE) to prevent race conditions during sensitive operations like invitation acceptance, ownership transfer, and role changes.
```ruby
invitation.accept!
org.transfer_ownership_to!(new_owner)
user.leave_organization!(org)
membership.promote_to!(:admin)
```
--------------------------------
### Get Current User's Organization Role
Source: https://context7.com/rameerez/organizations/llms.txt
Retrieves the current user's role within the active organization. This is a direct attribute access.
```ruby
current_user.current_organization_role # => :owner
```
--------------------------------
### Perform Efficient Existence Checks in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Illustrates the use of optimized SQL EXISTS queries for checking memberships and invitations, minimizing data transfer.
```ruby
user.belongs_to_any_organization?
user.has_pending_organization_invitations?
org.has_any_members?
```
--------------------------------
### Organizations Gem Basic Configuration
Source: https://context7.com/rameerez/organizations/llms.txt
This Ruby code snippet shows the basic configuration for the Organizations gem within a Rails initializer. It covers authentication methods, auto-creation settings, invitation defaults, and redirect paths.
```ruby
# config/initializers/organizations.rb
Organizations.configure do |config|
# === Authentication ===
config.current_user_method = :current_user
config.authenticate_user_method = :authenticate_user!
# === Auto-creation ===
config.always_create_personal_organization_for_each_user = false
config.default_organization_name = ->(user) { "#{user.name}'s Workspace" }
# === Invitations ===
config.invitation_expiry = 7.days
config.default_invitation_role = :member
config.invitation_mailer = "Organizations::InvitationMailer"
# === Limits ===
config.max_organizations_per_user = nil # unlimited
# === Redirects ===
config.redirect_path_when_no_organization = "/organizations/new"
config.redirect_path_after_invitation_accepted = "/dashboard"
config.redirect_path_after_organization_switched = "/dashboard"
# === Organizations Controller ===
config.additional_organization_params = [:support_email, :billing_email]
# === Handlers ===
config.on_unauthorized do |context|
redirect_to root_path, alert: "You don't have permission."
end
config.on_no_organization do |context|
redirect_to new_organization_path, notice: "Please create an organization."
end
end
```
--------------------------------
### Set Up Test Helpers for Organizations Gem
Source: https://github.com/rameerez/organizations/blob/main/README.md
Include the `Organizations::TestHelpers` module in your `ActiveSupport::TestCase` to gain access to helpful methods for testing organization-related functionality. This includes methods for signing in users and setting the current organization context.
```ruby
# test/test_helper.rb
require "organizations/test_helpers"
class ActiveSupport::TestCase
include Organizations::TestHelpers
end
```
--------------------------------
### Integrate acts_as_tenant
Source: https://context7.com/rameerez/organizations/llms.txt
Configures automatic query scoping by including the Organizations controller mixins and applying acts_as_tenant to models.
```ruby
class ApplicationController < ActionController::Base
include Organizations::Controller
include Organizations::ActsAsTenantIntegration
end
class Project < ApplicationRecord
acts_as_tenant :organization
end
```
--------------------------------
### Accept Organization Invitations
Source: https://context7.com/rameerez/organizations/llms.txt
Details how to handle invitation acceptance, including direct controller acceptance and automatic acceptance after signup/signin. It also shows manual acceptance with more control over the outcome.
```ruby
# In controller - accepting invitation directly
invitation = Organizations::Invitation.find_by(token: params[:token])
if invitation.pending?
membership = invitation.accept!(current_user)
redirect_to root_path, notice: "Welcome to #{invitation.organization.name}!"
end
```
```ruby
# Auto-accept pending invitation after signup/signin
# Add to ApplicationController
def after_sign_in_path_for(resource)
if (path = pending_invitation_acceptance_redirect_path_for(resource))
return path
end
super
end
def after_sign_up_path_for(resource)
if (path = pending_invitation_acceptance_redirect_path_for(resource))
return path
end
super
end
```
```ruby
# Manual acceptance with more control
result = accept_pending_organization_invitation!(current_user)
if result
result.accepted? # => true if freshly accepted
result.already_member? # => true if user was already a member
result.switched? # => true if org context was switched
result.invitation # => the invitation record
result.membership # => the membership record
end
```
--------------------------------
### Mount Organizations Engine Routes
Source: https://context7.com/rameerez/organizations/llms.txt
Shows how to mount the Organizations engine in your Rails application's `config/routes.rb` file to integrate its routing.
```ruby
# config/routes.rb
Rails.application.routes.draw do
mount Organizations::Engine => '/'
# Your other routes...
end
```
--------------------------------
### Send Organization Invitations
Source: https://context7.com/rameerez/organizations/llms.txt
Illustrates how to send invitations to users via email, either to the current organization or a specific one. It covers the organization-centric API and checking invitation status.
```ruby
# Invite to current organization (most common)
invitation = current_user.send_organization_invite_to!("teammate@example.com")
# Sends email: "John invited you to join Acme Corp"
# When accepted, user joins as :member (default role)
```
```ruby
# Invite to a specific organization
invitation = current_user.send_organization_invite_to!(
"teammate@example.com",
organization: other_org
)
```
```ruby
# Organization-centric API alternative
invitation = org.send_invite_to!(
"teammate@example.com",
invited_by: current_user
)
```
```ruby
# Check invitation status
invitation.pending? # => true
invitation.accepted? # => false
invitation.expired? # => false
invitation.status # => :pending
```
```ruby
# Resend expired invitation
invitation.resend! if invitation.expired?
```
--------------------------------
### Organizations Gem Lifecycle Callbacks
Source: https://context7.com/rameerez/organizations/llms.txt
This Ruby code snippet illustrates how to hook into various organization lifecycle events using the Organizations gem. It includes callbacks for organization creation, member invitations, member joining/removal, role changes, and ownership transfers, allowing for custom actions like notifications and analytics tracking.
```ruby
# config/initializers/organizations.rb
Organizations.configure do |config|
config.on_organization_created do |ctx|
SlackNotifier.notify("New org: #{ctx.organization.name}")
Analytics.track(ctx.user, "organization_created")
end
# Strict callback - can veto invitations (e.g., seat limits)
config.on_member_invited do |ctx|
org = ctx.organization
limit = org.current_plan.limit_for(:organization_members)
if limit && org.member_count >= limit
raise Organizations::InvitationError, "Member limit reached."
end
end
config.on_member_joined do |ctx|
WelcomeMailer.send_team_welcome(ctx.user, ctx.organization).deliver_later
Analytics.track(ctx.user, "joined_organization", org: ctx.organization.name)
end
config.on_member_removed do |ctx|
AuditLog.record(
action: :member_removed,
organization: ctx.organization,
user: ctx.user,
actor: ctx.removed_by
)
end
config.on_role_changed do |ctx|
Notification.send(ctx.user, "Your role changed to #{ctx.new_role}")
end
config.on_ownership_transferred do |ctx|
AuditLog.record(
action: :ownership_transferred,
organization: ctx.organization,
old_owner: ctx.old_owner,
new_owner: ctx.new_owner
)
end
end
```
--------------------------------
### Optimize Role Checks with Preloaded Data in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how to check user roles against organizations efficiently by leveraging preloaded membership data to avoid redundant database queries.
```ruby
user.organizations.includes(:memberships).each do |org|
user.is_admin_of?(org)
end
user.is_admin_of?(some_org)
```
--------------------------------
### Configure Custom Roles and Permissions (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Shows how to define custom roles and permissions within the organizations gem initializer. This allows for fine-grained control over what actions users can perform based on their assigned role.
```ruby
# config/initializers/organizations.rb
Organizations.configure do |config|
config.roles do
role :viewer do
can :view_organization
can :view_members
end
role :member, inherits: :viewer do
can :create_resources
can :edit_own_resources
can :delete_own_resources
end
role :admin, inherits: :member do
can :invite_members
can :remove_members
can :edit_member_roles
can :manage_settings
end
role :owner, inherits: :admin do
can :manage_billing
can :transfer_ownership
can :delete_organization
end
end
end
```
--------------------------------
### ERB Template for Organization Switcher and Permissions
Source: https://context7.com/rameerez/organizations/llms.txt
This ERB template demonstrates how to implement an organization switcher and conditionally render UI elements based on user roles and permissions. It utilizes data provided by `organization_switcher_data` and checks user permissions like `has_organization_permission_to?` and `is_organization_admin?`.
```erb
<% data = organization_switcher_data %>
<% if current_user.has_organization_permission_to?(:invite_members) %>
<%= link_to "Invite teammate", new_organization_invitation_path %>
<% end %>
<% if current_user.is_organization_admin? %>
<%= link_to "Settings", organization_settings_path %>
<% end %>
<%= organization_invitation_badge(current_user) %>
<%= organization_role_label(:admin) %>
<% organization_members_data(@org).each do |member| %>
<%= member[:name] %> - <%= member[:role_label] %>
<% end %>
```
--------------------------------
### Handle Existing Organization Invitations (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how the organizations gem handles scenarios where an email is already invited or an invitation has already been accepted. It returns the existing pending invitation or membership without raising an error.
```ruby
current_user.send_organization_invite_to!("already@invited.com")
# => Returns existing pending invitation (doesn't raise)
invitation.accept!
# => Returns existing membership (doesn't raise)
```
--------------------------------
### Database Schema Definitions
Source: https://github.com/rameerez/organizations/blob/main/README.md
Outlines the structure of the three core tables required by the gem: organizations_organizations, organizations_memberships, and organizations_invitations.
```sql
organizations_organizations
- id (primary key)
- name (string, required)
- metadata (jsonb, default: {})
- created_at
- updated_at
organizations_memberships
- id (primary key)
- user_id (foreign key, indexed)
- organization_id (foreign key, indexed)
- role (string, default: 'member')
- invited_by_id (foreign key, nullable)
- created_at
- updated_at
organizations_invitations
- id (primary key)
- organization_id (foreign key, indexed)
- email (string, required, indexed)
- role (string, default: 'member')
- token (string, unique, indexed)
- invited_by_id (foreign key, nullable)
- accepted_at (datetime, nullable)
- expires_at (datetime)
- created_at
- updated_at
```
--------------------------------
### Send Organization Invitations (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how to send invitations to users to join an organization. It covers inviting to the current organization or a specific one, and mentions that invitees default to the `:member` role. Authorization checks are enforced.
```ruby
# Invite to your current organization (most common)
current_user.send_organization_invite_to!("teammate@example.com")
# Invite to a specific organization
current_user.send_organization_invite_to!("teammate@example.com", organization: other_org)
# All invitees join as :member by default. Admins can promote after joining.
# Organization-centric API
org.send_invite_to!("teammate@example.com", invited_by: current_user)
> **Note:** Both APIs enforce authorization. The inviter must be a member of the organization with the `:invite_members` permission. If not, `Organizations::NotAMember` or `Organizations::NotAuthorized` is raised.
```
--------------------------------
### Check Roles in Current Organization
Source: https://context7.com/rameerez/organizations/llms.txt
Explains how to perform role checks for a user within the context of the current organization. This includes quick boolean checks for owner, admin, member, and viewer roles, as well as a general check for having at least a specific role.
```ruby
# Quick role checks (in current organization)
current_user.is_organization_owner? # => true/false
current_user.is_organization_admin? # => true/false (owners inherit admin)
current_user.is_organization_member? # => true/false
current_user.is_organization_viewer? # => true/false
```
```ruby
# Check if user has at least a specific role
current_user.has_organization_role?(:admin) # => true if admin or owner
```
--------------------------------
### Execute Scoped Associations with SQL JOINs in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how the gem uses SQL JOINs to fetch related records like admins or owned organizations efficiently.
```ruby
org.admins
user.owned_organizations
```
--------------------------------
### Manage Organization Members (Ruby)
Source: https://context7.com/rameerez/organizations/llms.txt
Provides methods to programmatically manage members of an organization, including adding, removing, changing roles, and transferring ownership. It also allows querying member lists and counts, and checking for the existence of specific members.
```ruby
# Add a user as member
org.add_member!(user, role: :member)
org.add_member!(user, role: :admin)
# Remove a member
org.remove_member!(user, removed_by: current_user)
# Change a user's role
org.change_role_of!(user, to: :admin, changed_by: current_user)
# Transfer ownership (new owner must be admin)
org.transfer_ownership_to!(admin_user)
# Old owner becomes admin automatically
# Membership role changes
membership = user.memberships.find_by(organization: org)
membership.promote_to!(:admin, changed_by: current_user)
membership.demote_to!(:member, changed_by: current_user)
# Query members
org.owner # => User (the owner)
org.admins # => [User, User] (admins including owner)
org.members # => all users
org.member_count # => 5
org.has_member?(user) # => true/false
org.has_any_members? # => true/false
```
--------------------------------
### Switch Active Organization (Ruby)
Source: https://context7.com/rameerez/organizations/llms.txt
Handles scenarios where a user belongs to multiple organizations. It allows retrieving all of a user's organizations, switching the active organization, and checking the current active organization. It also includes functionality for a user to leave an organization.
```ruby
# Get all user's organizations
current_user.organizations # => [acme, startup_co, personal]
# Switch active organization
switch_to_organization!(startup_co)
# In controller - switching
def switch
org = current_user.organizations.find(params[:id])
switch_to_organization!(org)
redirect_to dashboard_path
end
# Check current organization
current_organization # => Active organization from session
organization_signed_in? # => Is there an active organization?
# Leave an organization
current_user.leave_organization!(org)
current_user.leave_current_organization!
```
--------------------------------
### Manage Organization Context and Sessions
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how to access a user's organizations and switch the active organization within the current session.
```ruby
current_user.organizations # => [acme, startup_co, personal]
switch_to_organization!(startup_co) # Changes active org in session
```
--------------------------------
### Build Organization Switcher UI (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Provides a Ruby helper to build a user interface for switching between organizations. It requires data containing the current organization and a list of other organizations, along with a path for switching. The output is an HTML structure for a dropdown switcher.
```ruby
<% data = organization_switcher_data %>
```
--------------------------------
### Handle User Organization State in Views
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how to conditionally render partials based on whether a user belongs to an organization using ERB templates.
```erb
<% if current_user.belongs_to_any_organization? %>
<%= render "dashboard" %>
<% else %>
<%= render "onboarding/create_or_join_organization" %>
<% end %>
```
--------------------------------
### Integrate Pricing Plans for Member Limits
Source: https://github.com/rameerez/organizations/blob/main/README.md
Integrate with the `pricing_plans` gem to enforce member limits based on subscription tiers. This involves including `PricingPlans::PlanOwner` in the Organization model and defining plan limits in an initializer.
```ruby
# In your Organization model
class Organization < ApplicationRecord
include PricingPlans::PlanOwner
end
# In config/initializers/pricing_plans.rb
plan :starter do
limits :members, to: 5
end
plan :pro do
limits :members, to: 50
end
```
--------------------------------
### Enforce Plan Limits via Callbacks
Source: https://github.com/rameerez/organizations/blob/main/README.md
Integrates with pricing_plans to define member limits per plan and uses the on_member_invited callback to enforce these limits before an invitation is persisted.
```ruby
# config/initializers/pricing_plans.rb
plan :hobby do
limits :organization_members, to: 3
end
plan :growth do
limits :organization_members, to: 25
end
# config/initializers/organizations.rb
Organizations.configure do |config|
config.on_member_invited do |ctx|
org = ctx.organization
limit = org.current_plan.limit_for(:organization_members)
if limit && org.member_count >= limit
raise Organizations::InvitationError, "Member limit reached. Please upgrade your plan."
end
end
end
```
--------------------------------
### Database Indexes for Organizations Gem (SQL)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Defines the SQL database indexes automatically created by the organizations gem for efficient lookups of memberships and invitations. These include unique indexes for user/organization pairs and tokens, as well as indexes for organization ID, role, and email.
```sql
-- Fast membership lookups
CREATE UNIQUE INDEX index_organizations_memberships_on_user_and_org ON organizations_memberships (user_id, organization_id);
CREATE INDEX index_organizations_memberships_on_organization_id ON organizations_memberships (organization_id);
CREATE INDEX index_organizations_memberships_on_role ON organizations_memberships (role);
-- Fast invitation lookups
CREATE UNIQUE INDEX index_organizations_invitations_on_token ON organizations_invitations (token);
CREATE INDEX index_organizations_invitations_on_email ON organizations_invitations (email);
CREATE UNIQUE INDEX index_organizations_invitations_pending ON organizations_invitations (organization_id, LOWER(email)) WHERE accepted_at IS NULL;
```
--------------------------------
### Configure Organization Settings
Source: https://github.com/rameerez/organizations/blob/main/README.md
Customize the gem's behavior, including redirect paths, mailer classes, and invitation expiration periods via an initializer.
```ruby
Organizations.configure do |config|
config.redirect_path_when_invitation_requires_authentication = "/users/sign_up"
config.redirect_path_after_invitation_accepted = ->(inv, user) { "/org/#{inv.organization_id}/welcome" }
config.invitation_mailer = "Organizations::InvitationMailer"
config.invitation_expiry = 7.days
end
```
--------------------------------
### Rails Helper for Organization View Logic
Source: https://context7.com/rameerez/organizations/llms.txt
This Ruby helper module integrates view-specific organization functionalities, such as rendering an organization switcher and conditionally displaying links based on user permissions. It relies on `Organizations::ViewHelpers` and Rails view helpers.
```ruby
module ApplicationHelper
include Organizations::ViewHelpers
end
```
--------------------------------
### Retrieve Lightweight Organization Switcher Data in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Provides a helper method to fetch minimal organization data for UI navigation, memoizing the result within the request cycle.
```ruby
organization_switcher_data
```
--------------------------------
### User Organization Actions
Source: https://github.com/rameerez/organizations/blob/main/README.md
Defines actions users can perform related to organizations, such as creating, leaving, and sending invitations. Supports both positional and keyword arguments for organization creation.
```ruby
# Actions
user.create_organization!("Acme") # Positional arg
user.create_organization!(name: "Acme") # Keyword arg (both work)
user.leave_organization!(org)
user.leave_current_organization! # Leave the active org
user.send_organization_invite_to!(email) # Invite to current org
user.send_organization_invite_to!(email, organization: org) # Invite to specific org
```
--------------------------------
### Configure Unauthorized Access Handling
Source: https://github.com/rameerez/organizations/blob/main/README.md
Define global behavior for unauthorized access or missing organization context within the gem's configuration initializer.
```ruby
Organizations.configure do |config|
config.on_unauthorized do |context|
redirect_to root_path, alert: "You don't have permission to do that."
end
config.on_no_organization do |context|
redirect_to new_organization_path, alert: "Please create or join an organization first."
end
end
```
--------------------------------
### Check Specific Organization Roles (Ruby)
Source: https://context7.com/rameerez/organizations/llms.txt
Allows checking a user's role within a particular organization instance. It supports direct role comparison and checks for specific roles like owner, admin, member, and viewer. It also enables checking if the user's role meets a minimum level.
```ruby
# Check role in a specific organization
current_user.role_in(@org) # => :admin
# Role checks for specific organization
current_user.is_owner_of?(@org) # => true/false
current_user.is_admin_of?(@org) # => true/false
current_user.is_member_of?(@org) # => true/false
current_user.is_viewer_of?(@org) # => true/false
# Check minimum role level
current_user.is_at_least?(:admin, in: @org) # => true if admin or owner
```
--------------------------------
### Manage Organizations and Invitations
Source: https://github.com/rameerez/organizations/blob/main/README.md
Perform core organization actions such as creating new organizations, inviting teammates via email, and switching the active organization context.
```ruby
current_user.create_organization!("Acme Corp")
current_user.send_organization_invite_to!("teammate@acme.com")
switch_to_organization!(@org)
```
--------------------------------
### Extend Organization Model
Source: https://context7.com/rameerez/organizations/llms.txt
Demonstrates how to use class_eval to add associations, validations, and custom methods to the Organizations::Organization model.
```ruby
Organizations::Organization.class_eval do
has_many :projects
has_many :documents
validates :support_email, format: { with: URI::MailTo::EMAIL_REGEXP }, allow_blank: true
def active_projects
projects.where(archived: false)
end
end
```
--------------------------------
### Extend Organization Model
Source: https://github.com/rameerez/organizations/blob/main/README.md
Demonstrates how to extend the base Organizations model using class_eval for dynamic modification or by creating a subclass for domain-specific logic.
```ruby
Organizations::Organization.class_eval do
has_many :projects
has_many :documents
validates :support_email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
def active_projects
projects.where(archived: false)
end
end
```
```ruby
class Organization < Organizations::Organization
has_many :projects
has_many :documents
validates :support_email, presence: true
end
```
--------------------------------
### Organization Associations and Queries
Source: https://github.com/rameerez/organizations/blob/main/README.md
Provides methods for accessing organization members, users, invitations, and performing queries like checking for members or counting them. Includes class methods for organization scopes.
```ruby
# Associations
org.memberships # All memberships
org.members # All users (alias for org.users)
org.users # All users (through memberships)
org.invitations # All invitations (pending + accepted)
org.pending_invitations # Invitations not yet accepted
# Queries
org.owner # User who owns this org
org.admins # Users with admin role or higher
org.has_member?(user) # "Does org have this user as a member?"
org.has_any_members? # "Does org have any members?"
org.member_count # Number of members
# Class methods / Scopes
Organizations::Organization.with_member(user) # Find all orgs where user is a member
```
--------------------------------
### Access Member Counts via Counter Cache in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Shows how to retrieve organization member counts efficiently using the built-in memberships_count counter cache.
```ruby
org.member_count
```
--------------------------------
### Organization Actions and Invitations
Source: https://github.com/rameerez/organizations/blob/main/README.md
Enables managing organization members, changing roles, transferring ownership, and sending invitations. Invitation sending can auto-infer the inviter or specify it explicitly.
```ruby
# Actions
org.add_member!(user, role: :member)
org.remove_member!(user)
org.change_role_of!(user, to: :admin)
org.transfer_ownership_to!(other_user)
# Invitations (inviter must be a member with :invite_members permission)
org.send_invite_to!(email) # Auto-infers invited_by from Current.user
org.send_invite_to!(email, invited_by: user) # Explicit inviter
```
--------------------------------
### Integrate Invitation Acceptance into Auth Flow
Source: https://github.com/rameerez/organizations/blob/main/README.md
Use these helpers in your ApplicationController to handle pending invitations after a user signs in or signs up. This ensures that users who clicked an invitation link while logged out are correctly associated with the organization upon authentication.
```ruby
def after_sign_in_path_for(resource)
if (path = pending_invitation_acceptance_redirect_path_for(resource))
return path
end
super
end
def after_sign_up_path_for(resource)
if (path = pending_invitation_acceptance_redirect_path_for(resource))
return path
end
super
end
```
--------------------------------
### Invitation Details and Status Checks
Source: https://github.com/rameerez/organizations/blob/main/README.md
Exposes details of an invitation, including the invited email, organization, role, and inviter. Allows checking the status of an invitation (pending, accepted, expired).
```ruby
invitation.email # => "teammate@example.com"
invitation.organization # The organization
invitation.role # Role they'll have when accepted
invitation.invited_by # User who sent the invitation
invitation.from # Alias for invited_by
invitation.pending? # => true (not yet accepted)
invitation.accepted? # => true (has accepted_at)
invitation.expired? # => true (past expires_at)
```
--------------------------------
### Integrate with acts_as_tenant for Scoping
Source: https://github.com/rameerez/organizations/blob/main/README.md
Include the `Organizations::Controller` and `Organizations::ActsAsTenantIntegration` concerns in your `ApplicationController` to automatically scope queries based on the current organization. This integration simplifies tenant-specific data management.
```ruby
class ApplicationController < ActionController::Base
include Organizations::Controller
include Organizations::ActsAsTenantIntegration
# Automatically calls: set_current_tenant(current_organization)
end
```
--------------------------------
### Configure Organizations Engine
Source: https://github.com/rameerez/organizations/blob/main/README.md
The primary configuration block for the Organizations gem. It defines authentication methods, invitation settings, redirect paths, and lifecycle hooks for organization management.
```ruby
Organizations.configure do |config|
config.current_user_method = :current_user
config.authenticate_user_method = :authenticate_user!
config.invitation_expiry = 7.days
config.redirect_path_when_no_organization = "/organizations/new"
config.after_organization_created_redirect_path = "/dashboard"
config.on_organization_created do |ctx|
# Handle organization creation logic
end
end
```
--------------------------------
### Configure Authentication Methods
Source: https://github.com/rameerez/organizations/blob/main/README.md
Configure custom user methods for authentication when using Rodauth, Sorcery, or other auth systems. This involves setting the `current_user_method` and `authenticate_user_method` in the Organizations configuration.
```ruby
Organizations.configure do |config|
config.current_user_method = :current_account
config.authenticate_user_method = :require_login
end
```
--------------------------------
### Integrate with Rameerez Gem Ecosystem
Source: https://github.com/rameerez/organizations/blob/main/README.md
Integrate the Organizations gem with other gems in the rameerez ecosystem, such as `api_keys`, `usage_credits`, and `pricing_plans`. This allows organizations to manage API keys, credits, and pricing plans directly.
```ruby
# Organization owns API keys (api_keys gem)
class Organization < ApplicationRecord
has_api_keys do
max_keys 10
end
end
# Organization has credits (usage_credits gem)
class Organization < ApplicationRecord
has_credits
end
# Organization has pricing plan (pricing_plans gem)
class Organization < ApplicationRecord
include PricingPlans::PlanOwner
end
# Accessing through current_organization
current_organization.api_keys
current_organization.credits
current_organization.current_pricing_plan
current_organization.memberships
```
--------------------------------
### Organizations Gem Custom Role Definitions
Source: https://context7.com/rameerez/organizations/llms.txt
This Ruby code snippet defines custom roles and their associated permissions within the Organizations gem. It demonstrates role inheritance and how to check for specific permissions using `has_organization_permission_to?` and `require_organization_permission_to!`.
```ruby
# config/initializers/organizations.rb
Organizations.configure do |config|
config.roles do
role :viewer do
can :view_organization
can :view_members
end
role :member, inherits: :viewer do
can :create_resources
can :edit_own_resources
can :delete_own_resources
end
role :admin, inherits: :member do
can :invite_members
can :remove_members
can :edit_member_roles
can :manage_settings
can :view_billing
can :manage_api_keys # Custom permission
can :export_data # Custom permission
end
role :owner, inherits: :admin do
can :manage_billing
can :transfer_ownership
can :delete_organization
end
end
end
# Check custom permissions
current_user.has_organization_permission_to?(:manage_api_keys)
require_organization_permission_to!(:export_data)
```
--------------------------------
### Add Custom Permissions to Roles (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Illustrates how to add custom permissions to existing roles, such as `:admin`. It also shows how to check for these custom permissions using `has_organization_permission_to?` and `require_organization_permission_to!`.
```ruby
role :admin, inherits: :member do
can :invite_members
can :remove_members
can :manage_api_keys # Your custom permission
can :export_data # Your custom permission
end
current_user.has_organization_permission_to?(:manage_api_keys)
require_organization_permission_to!(:export_data)
```
--------------------------------
### Add Custom Fields to Organizations Migration
Source: https://context7.com/rameerez/organizations/llms.txt
A Rails migration to extend the organizations table with support email, billing address, and a JSONB settings column.
```ruby
class AddCustomFieldsToOrganizations < ActiveRecord::Migration[8.0]
def change
add_column :organizations_organizations, :support_email, :string
add_column :organizations_organizations, :billing_address, :text
add_column :organizations_organizations, :settings, :jsonb, default: {}
end
end
```
--------------------------------
### Implement Request-Level Memoization in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Explains the memoization of the current_organization object within a controller request to prevent repeated database lookups.
```ruby
current_organization
```
--------------------------------
### Add Existing Member to Organization (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
Shows how the organizations gem adds an existing user to an organization. If the user is already a member, it returns the existing membership without raising an error.
```ruby
org.add_member!(existing_user)
# => Returns existing membership (doesn't raise)
```
--------------------------------
### Check Organization Permissions (Ruby)
Source: https://context7.com/rameerez/organizations/llms.txt
Verifies specific permissions for the current user within the active organization or a specific membership. It leverages a pre-computed permission system. Permissions can be checked directly on the user or through their membership object. It also allows checking permissions against predefined roles.
```ruby
# Check permission in current organization
current_user.has_organization_permission_to?(:invite_members) # => true/false
current_user.has_organization_permission_to?(:manage_billing) # => true/false
current_user.has_organization_permission_to?(:manage_settings) # => true/false
# Membership-level permission check
membership = current_user.current_membership
membership.has_permission_to?(:invite_members) # => true/false
membership.permissions # => [:view_members, :invite_members, ...]
# Direct Roles module access
Organizations::Roles.has_permission?(:admin, :invite_members) # => true
Organizations::Roles.has_permission?(:member, :invite_members) # => false
Organizations::Roles.permissions_for(:admin) # => [:view_organization, :invite_members, ...]
```
--------------------------------
### Manage Atomic Transaction Boundaries in Ruby
Source: https://github.com/rameerez/organizations/blob/main/README.md
Shows how multi-step operations are wrapped in database transactions to ensure atomicity and data integrity.
```ruby
user.create_organization!("Acme")
invitation.accept!
org.transfer_ownership_to!(user)
```
--------------------------------
### Configure Organization Lifecycle Callbacks
Source: https://github.com/rameerez/organizations/blob/main/README.md
Configure callbacks to hook into organization lifecycle events such as creation, member joining/removal, role changes, and ownership transfers. These callbacks can trigger notifications, analytics, or validation.
```ruby
Organizations.configure do |config|
config.on_organization_created do |ctx|
SlackNotifier.notify("New org: #{ctx.organization.name}")
Analytics.track(ctx.user, "organization_created")
end
config.on_member_joined do |ctx|
WelcomeMailer.send_team_welcome(ctx.user, ctx.organization).deliver_later
Analytics.track(ctx.user, "joined_organization", org: ctx.organization.name)
end
config.on_member_removed do |ctx|
AuditLog.record(
action: :member_removed,
organization: ctx.organization,
user: ctx.user,
actor: ctx.removed_by
)
end
end
```
--------------------------------
### Configure Organization Auto-Creation
Source: https://github.com/rameerez/organizations/blob/main/README.md
Configures the engine to automatically create a personal organization upon user signup. It allows customization of the organization name via a lambda function.
```ruby
Organizations.configure do |config|
config.always_create_personal_organization_for_each_user = true
config.default_organization_name = ->(user) { "#{user.email.split('@').first}'s Workspace" }
end
```
--------------------------------
### Controller Guards for Organization Context (Ruby)
Source: https://context7.com/rameerez/organizations/llms.txt
Provides controller concerns and helper methods to enforce organization context and perform role/permission checks within controllers. This includes guards for requiring an organization to be set, specific roles, or specific permissions before allowing controller actions.
```ruby
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include Organizations::Controller # or Organizations::ControllerHelpers
end
# Protect controllers with before_action guards
class ProjectsController < ApplicationController
before_action :require_organization!
before_action :require_organization_admin!, only: [:create, :destroy]
def billing
require_organization_owner! # Only owners can manage billing
end
end
# Permission-based guards
class SettingsController < ApplicationController
before_action :require_organization!
before_action -> { require_organization_permission_to!(:manage_settings) }
end
# Available guards
# require_organization! - Requires current org to be set
# require_organization_role!(:admin) - Requires at least admin role
# require_organization_admin! - Shortcut for admin role
# require_organization_owner! - Shortcut for owner role
# require_organization_permission_to!(:action) - Requires specific permission
```
--------------------------------
### Minitest Assertions for Organization Permissions
Source: https://github.com/rameerez/organizations/blob/main/README.md
Use provided Minitest assertions to easily check user roles and permissions within organizations. These assertions simplify common checks like membership, ownership, admin status, and specific permissions.
```ruby
assert user.is_member_of?(org)
assert user.is_owner_of?(org)
assert user.is_organization_admin?
assert user.has_organization_permission_to?(:invite_members)
assert user.belongs_to_any_organization?
```
--------------------------------
### Switch Organizations Manually
Source: https://github.com/rameerez/organizations/blob/main/README.md
Update the current organization context for a user by calling the switch helper within a controller action. This updates the session and ensures subsequent queries are scoped to the new organization.
```ruby
def switch
org = current_user.organizations.find(params[:id])
switch_to_organization!(org)
redirect_to dashboard_path
end
```
--------------------------------
### Handle Invitation Acceptance Results
Source: https://github.com/rameerez/organizations/blob/main/README.md
Process the result of an invitation acceptance, which returns an object containing membership details or failure reasons. This allows for conditional logic based on whether the user was already a member or if the invitation was successfully accepted.
```ruby
result = accept_pending_organization_invitation!(user, return_failure: true)
if result.success?
# InvitationAcceptanceResult
else
# InvitationAcceptanceFailure
result.failure_reason # => :missing_token, :email_mismatch, :invitation_expired, etc.
end
```
--------------------------------
### Reset and Layout CSS for 404 Page
Source: https://github.com/rameerez/organizations/blob/main/test/dummy/public/404.html
This CSS snippet provides a global reset, typography settings, and a centered grid layout for the error page. It uses modern CSS features like clamp() for fluid typography and media queries for responsive adjustments.
```css
*,
*::before,
*::after { box-sizing: border-box; }
* { margin: 0; }
html { font-size: 16px; }
body { background: #FFF; color: #261B23; display: grid; font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, Aptos, Roboto, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: clamp(1rem, 2.5vw, 2rem); -webkit-font-smoothing: antialiased; font-style: normal; font-weight: 400; letter-spacing: -0.0025em; line-height: 1.4; min-height: 100vh; place-items: center; text-rendering: optimizeLegibility; -webkit-text-size-adjust: 100%; }
a { color: inherit; font-weight: 700; text-decoration: underline; text-underline-offset: 0.0925em; }
b, strong { font-weight: 700; }
i, em { font-style: italic; }
main { display: grid; gap: 1em; padding: 2em; place-items: center; text-align: center; }
main header { width: min(100%, 12em); }
main header svg { height: auto; max-width: 100%; width: 100%; }
main article { width: min(100%, 30em); }
main article p { font-size: 75%; }
main article br { display: none; @media(min-width: 48em) { display: inline; } }
```
--------------------------------
### Configure Controller Integration
Source: https://github.com/rameerez/organizations/blob/main/README.md
Integrate the organization management functionality into your Rails application by including the controller concern in the ApplicationController.
```ruby
class ApplicationController < ActionController::Base
include Organizations::Controller
end
```
--------------------------------
### Perform Permission Checks in Views
Source: https://github.com/rameerez/organizations/blob/main/README.md
Use helper methods to conditionally display UI elements based on the current user's organization permissions or roles.
```ruby
<% if current_user.has_organization_permission_to?(:invite_members) %>
<%= link_to "Invite teammate", new_invitation_path %>
<% end %>
<% if current_user.is_organization_admin? %>
<%= link_to "Settings", organization_settings_path %>
<% end %>
```
--------------------------------
### Display Organization Invitation Count Badge (Ruby)
Source: https://github.com/rameerez/organizations/blob/main/README.md
A Ruby helper function to display a badge indicating the number of pending organization invitations for the current user. If there are no pending invitations, it returns nil. This is typically used in a navigation bar.
```ruby
# Show pending invitation count in your navbar
<%= organization_invitation_badge(current_user) %>
# => 3 (if 3 pending invitations)
# => nil (if no pending invitations)
```
--------------------------------
### Define User Model Organization Requirements
Source: https://github.com/rameerez/organizations/blob/main/README.md
Configures the User model to enforce organization membership and enable automatic personal organization creation during the signup process.
```ruby
class User < ApplicationRecord
has_organizations do
create_personal_org true
require_organization true
end
end
```