Reputation: 467
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
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