justin henricks
justin henricks

Reputation: 467

Rails: Devise and acts_as_tenant registration process

I am using acts_as_tenant gem to manage a multi-tenant platform while using devise to manage users. A User in our system acts_as_tenant and belongs_to Organization. Organization acts_as_tenant and has_many Users.

We are having trouble understanding what the best way to ensure that upon sign up a User gets created, an Organization gets created, a Tenant gets created (based on the Org), and the current tenant gets saved subsequently setting the correct tenant_id on the User and Org model.

The problem is in order for a User to be valid it must have an organization and a tenant. So before validation happens we must create the org and the tenant, we are trying to do so with below code:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable

  acts_as_tenant(:tenant)
  acts_as_paranoid
  belongs_to :organization

  before_validation :create_organization

  def create_organization
    if self.organization_id.nil?
      org = Organization.new(name: self.email)
      org.uuid = UUIDTools::UUID.random_create.to_s
      self.organization_id = org.uuid
    end
  end
end
class Organization < ApplicationRecord
  acts_as_tenant(:tenant)
  self.primary_key = :uuid
  has_many :users

  before_validation :create_tenant

  def create_tenant
    puts 'making new tenant'
    t = Tenant.new(:short_name => self.name)
  end
end
class ApplicationController < ActionController::Base
  set_current_tenant_through_filter
  before_action :find_current_tenant
  def find_current_tenant
    unless current_user.nil?
      set_current_tenant(current_user.organization.tenant)
    end
  end
end

But the users org and tenant are not being created before validation causing validation errors 'tenant must exist', 'org must exist'.

Any help on best practices here?

Upvotes: 0

Views: 987

Answers (1)

Leticia Esperon
Leticia Esperon

Reputation: 2861

I don't know your business logic but in order to do acts_as_tenant(:tenant) your model has to have a relation defined to tenant, which you don't seem to have. I think what you want to do (common use case) is:

class User < ActionController::Base
  belongs_to :organization
  acts_as_tenant(:organization)
end

class Organization < ActionController::Base
  self.primary_key = :uuid
  has_many :users
  # and nothing else
end

You don't set the current tenant on the model. That is not correct. You do that on the Application Controller, by doing set_current_tenant(current_user.organization) and nothing else

UPDATE: You mentionew a Tenant class now.

So now your organization class should define that relation

class Organization < ApplicationRecord
  acts_as_tenant(:tenant)
  self.primary_key = :uuid
  has_many :users
  belongs_to :tenant

  before_validation :create_tenant

  def create_tenant
    puts 'making new tenant'
    self.tenant ||= Tenant.create!(:short_name => self.name)
  end
end

Upvotes: 0

Related Questions