[英]Multitenant Rails model Inheritance
My multi-tenant "Customer" model represents data from multiple tables in a "org_#{current_user.org.id}_customers" pattern (ie org_1_customers, org_2_customers, etc). 我的多租户“客户”模型以“ org _#{current_user.org.id} _customers”模式(即org_1_customers,org_2_customers等)表示来自多个表的数据。 I'm using RequestStore gem to store current_user's ORG_ID.
我正在使用RequestStore gem存储current_user的ORG_ID。
So, the problem is that to access data of CURRENT organization, I have to explicitly call "Customer.org" (ie Customer.org.where(...).load). 因此,问题在于,要访问当前组织的数据,我必须显式调用“ Customer.org”(即Customer.org.where(...)。load)。 Which requires rewriting A LOT of code, and remembering to add "org" every time I access the data.
这需要重写大量代码,并且每次访问数据时都要记住添加“ org”。
MY QUESTION IS: Is there a way to make it so that I could access "Customer.org" by calling "Customer", so I would use "Customer" for current tenant's/org's customers, and "Customer.select_org(7)" for other tenant's/org's customers? 我的问题是:有没有一种方法可以使我可以通过调用“客户”来访问“ Customer.org”,因此我可以将“ Customer”用于当前租户/组织的客户,以及“ Customer.select_org(7)”。对于其他租户/组织的客户?
class ApplicationController < ActionController::Base
before_filter :find_organization
private
def find_organization
RequestStore[:current_org] = current_user ? current_user.org : nil
end
end
class SegregatedMultitenantModel < ActiveRecord::Base
self.abstract_class = true
def self.select_org(org_id)
@subdomain_classes ||= {}
unless @subdomain_classes[org_id]
@subdomain_classes[org_id] ||= Class.new(self)
@subdomain_classes[org_id].table_name = "org_#{org_id}_#{self.table_name}" # This needs sanitizing, of course
@subdomain_classes[org_id].reset_column_information
end
@subdomain_classes[org_id]
end
def self.org
if RequestStore[:current_org].nil?
raise "No Organization Selected For #{self.table_name}"
else
self.select_org(RequestStore[:current_org].id)
end
end
end
class Customer < SegregatedMultitenantModel
end
PS My application does require multiple Customer tables due to differences in table fields between tenants! PS由于租户之间的表字段不同,我的应用程序确实需要多个Customer表!
I've come up with a solution! 我想出了一个解决方案! It scopes the rows by convention anywhere in the app and I'm satisfied with it:
它按约定在应用程序中的任何位置划定行的范围,我对此感到满意:
# Returns first row from "org_#{current_user.org.id}_customers" table
MT::Customer.first
# Returns first row from "org_3_customers" table
MT::Customer.select_org(3).first
To Do this, first, I segregated the "scoping" into a class: 为此,首先,我将“作用域”分为一个类:
class MT
@@segregated_organization_models = {}
def self.init(organizations, current_org, *options)
organizations.each do |org|
options[0][:segregated_models].each do |class_object|
# Create new model class
@@segregated_organization_models[org.id] ||= {}
a = Class.new(class_object)
@@segregated_organization_models[org.id][class_object.to_s.to_sym] = a
# Set correct table name
@@segregated_organization_models[org.id][class_object.to_s.to_sym].table_name = "org_#{org.id}_#{class_object.table_name}"
# Set default model class to current organization's model class
if org.id === current_org.id
self.const_set(class_object.to_s.to_sym, @@segregated_organization_models[org.id][class_object.to_s.to_sym])
end
end
end
end
end
while getting rid of the RequestStore gem and model logic in favor of the controller: 同时摒弃了RequestStore gem和模型逻辑以支持控制器:
class ApplicationController < ActionController::Base
before_filter :find_organization
private
# Multitenancy helpers
def find_organization
MT.init(Organization.all, current_user.org,
segregated_models: [
ArticleCategory, Article, CustomArticleField,
Customer, CustomerChange, CustomerLedgerItem
]
)
end
end
Model inheritance is still there: 模型继承仍然存在:
class SegregatedMultitenantModel < ActiveRecord::Base
self.abstract_class = true
def self.select_org(org_id)
MT.class_variable_get(:@@segregated_organization_models)[org_id][self.to_s.demodulize.to_sym]
end
end
class Customer < SegregatedMultitenantModel
self.abstract_class = true
self.table_name = "customers"
end
Thanks a lot to an anonymous commenter who since deleted his response. 非常感谢匿名评论者此后删除了他的回复。 Please don't delete your good responses with useful information!
请不要删除包含有用信息的良好回复! I have nothing to upvote.
我没有什么可投票的。 Lol.
大声笑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.