I'm implementing a multi-tenant app with Rails. My approach is not to use the postgres inbuilt multi-tenant feature and add a column to record the subdomain. That is where the question is :)
Let's get this example
class Organisation < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :organisation
end
I'm thinking about two approaches here:
Approach 1
add a subdomain
column only to organisations
Approach 2
add a subdomain
column to both organisations
and users
So the question is, what sort of a method I should follow between above two, or are there a different approach that I didn't think about?
my opinion will go Approach number one, couple reasons for this
I have a project with multi tenant capabilities and below is sample of design in my project
class Company < ApplicationRecord
has_many :users
# transaction
has_many :transactions
has_many :journals , :through => :transactions
# item
has_many :items
# other has_many ...
end
and in controller you can use eager loading to minimize query (includes / joins)
@company.includes(:users).scope_filter_here.search(params[:q])
We run a multi-tenant Rails app with slightly fewer than 500 table-backed classes, and if I had to guess I'd say around 400 of them relate to client data.
Client-specific attributes are held in the Client
model, but we add the client_id
to every client table with a not null constraint on the database. Only a minority of them are indexed, though because they are generally only accessed through a parent record.
We do not have to worry about setting the client id because the model will generally have:
class Child
after_initialize do
self.client ||= parent.client
end
end
We add the client_id
to many tables because we have a lot of code that does:
@books = current_user.client.books
... so in those cases we'll have an association directly from Client
to the model, and client_id
is indexed.
We add the client_id
to all tables, though, because we very often, for operational or unusual reasons, want to be able to find all of the relevant records for a client ...
MarketingText.where(client: Client.snowbooks).group(:type).count
... and having to go through a parent record is just inconvenient.
Also, because we made the decision to do this on all client-specific tables, we do not have to make the decision on each one.
So to get to your question, what I would do is add the subdomain to the Organisation
only. However, I would add the organisation_id
column to every table holding Organisation-specific data.
If you have a lot of clients but you are going to be generally familiar with their subdomain, then I would write a meta-program method on the Organisation that lets you use:
Organisation.some_subdomain
... to get the required organisation, then find the child records (in any table) with an association directly from the Organisation model ...
Organisation.some_subdomain.users
Organisation.some_subdomain.prices
Organisation.some_subdomain.whatevers
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.