Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Any way to achieve two level multi-tenancy? #203

Open
vit-panchuk opened this issue Jul 11, 2023 · 4 comments
Open

Any way to achieve two level multi-tenancy? #203

vit-panchuk opened this issue Jul 11, 2023 · 4 comments
Assignees

Comments

@vit-panchuk
Copy link

vit-panchuk commented Jul 11, 2023

Hello,

Thanks for implementing and supporting such a good gem we use in many of our projects!

We use the gem in our project to separate events such as fairs and conferences as tenants. They share users and have out-of-tenant configurations such as domains and routes, etc:

image

What we want is to add a completely new level of tenancy: vendors. Vendors should have their own separate scope of events, users and configurations:

image

As my experience with the activerecord-multi-tenant and common sense I see "Variant 2" as a viable option, where I would have two multi_tenant tables: events and vendors. On the contrary, events still should be dependent on vendors and it can mix up some stuff with database queries and the MultiTenant.current_tenant state.

"Variant 1" seems to me more logical and readable but I have no idea where to start with modifying the gem to make it work. I suppose it is doable to make it possible to pass the tenant as an array of a vendor and an event model as so: MultiTenant.with([current_vendor, current_event]) but I wanted to ask you, the authors, what you think about it.

@gurkanindibay
Copy link
Contributor

Hey @vit-panchuk

I can not see any difference between Variant 1 and Variant2. Could you explain the difference? And could you give me some examples in code blocks?

Thanks

@vit-panchuk
Copy link
Author

vit-panchuk commented Jul 11, 2023

@gurkanindibay, thx for the quick response!

Variant 1 would be considered something like that:

# vendors: id, name, etc
class Vendor < ApplicationRecord
end

# users: id, name, vendor_id, etc
class User < ApplicationRecord
  multi_tenant :vendor
end

# urls: id, domain, route, vendor_id, etc
class Url < ApplicationRecord
  multi_tenant :vendor
  has_one :event
end

# events: id, name, vendor_id, etc
class Event < ApplicationRecord
   multi_tenant :vendor
   belongs_to :url
end

# exhibitors: id, name, event_id, vendor_id, etc
class Exhibitor < ApplicationRecord
  multi_tenant :vendor, :event # obviously, pseudocode
end

The Event model itself would have multi_tenant :vendor.

The User model has only multi_tenant :vendor because users are shared among events of the same vendor but are not shared among vendors.

All models inside the event tenant (e.g. Exhibitor, SideEvent, Product) would need to have both event_id (already implemented) and vendor_id (needs to be added) references and they would know they are inside an event and inside a vendor.

Obviously, if I decide to go this way, MultiTenant.current_tenant and other MultiTenant API should be modified to recognize the hierarchy of tenants (vendors > events).

Variant 2:

# vendors: id, name, etc
class Vendor < ApplicationRecord
end

# users: id, name, vendor_id, etc
class User < ApplicationRecord
  multi_tenant :vendor
end

# urls: id, domain, route, vendor_id, etc
class Url < ApplicationRecord
  multi_tenant :vendor
  has_one :event
end

# events: id, name, vendor_id, etc
class Event < ApplicationRecord
   belongs_to :vendor # or maybe I can even use `multi_tenant :vendor` here?
   belongs_to :url
end

# exhibitors: id, name, event_id, etc
class Exhibitor < ApplicationRecord
  multi_tenant :event
end

This way I am getting two federated "islands" of tenants that know nothing about each other existence (e.g. Exhibitor model does not have a direct reference to a vendor but it is still inside an event). No MultiTenant modifications, etc, but I am not sure it actually possible to track two MultiTenant.current_tenant states simultaneously (one for current_vendor and another for current_event).

@gurkanindibay
Copy link
Contributor

You need to add vendor column into exhibitor table even if it is not required directly by your model. It is required by active record multitenant I know it is a de normalization but still we need since we can support one tenant at a time

@vit-panchuk
Copy link
Author

So you meant it actually possible to have something like this?:

# vendors: id, name, etc
class Vendor < ApplicationRecord
end

# events: id, name, vendor_id, etc
class Event < ApplicationRecord
   multi_tenant :vendor
end

# exhibitors: id, name, event_id, vendor_id, etc
class Exhibitor < ApplicationRecord
  multi_tenant :vendor
  multi_tenant :event
end

@serprex serprex assigned serprex and gurkanindibay and unassigned serprex Jul 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants