我的多租户"客户" model表示来自" org _#{current_user.org.id} _customers"中多个表的数据。模式(即org_1_customers,org_2_customers等)。我使用RequestStore gem来存储current_user的ORG_ID。
所以,问题是要访问CURRENT组织的数据,我必须明确地调用" Customer.org" (即Customer.org.where(...)。load)。这需要重写大量代码,并记住添加" org"每次我访问数据。
我的问题是:有没有办法让我能够访问" Customer.org"通过呼叫"客户",所以我会使用"客户"对于当前租户的组织客户,以及" 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
P.S。由于租户之间的表格字段不同,我的应用程序确实需要多个客户表!
答案 0 :(得分:0)
我想出了一个解决方案!它按照惯例在应用程序的任何位置对行进行范围调整,我对此感到满意:
# 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
要做到这一点,首先,我将“范围”分为一类:
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
同时摆脱了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
模型继承仍然存在:
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
非常感谢匿名评论者,因为他删除了他的回复。请不要删除有用信息的好回复!我没有什么可以投票的。洛尔。