假设我有5张桌子。 ActiveRecord可以处理这个吗?你会如何设置它?
层次结构:
Account (Abstract)
CorporateCustomer (Abstract)
PrivateCustomer
PublicCustomer
GovernmentCustomer
编辑:在nhibernate和castle activerecord中,启用此方案所需的方法称为“join-subclasses”。
答案 0 :(得分:4)
您可以尝试以下几行。
class Account < ActiveRecord::Base
belongs_to :corp_or_gov_customer, :polymorphic => true
def account_id
self.id
end
end
class GovernmentCustomer < ActiveRecord::Base
has_one :account, :as => :corp_or_gov_customer, :dependent => :destroy
def method_missing( symbol, *args )
self.account.send( symbol, *args )
end
end
class CorporateCustomer < ActiveRecord::Base
has_one :account, :as => :corp_or_gov_customer, :dependent => :destroy
belongs_to :priv_or_pub_customer, :polymorphic => true
def method_missing( symbol, *args )
self.account.send( symbol, *args )
end
end
class PrivateCustomer < ActiveRecord::Base
has_one :corporate_customer, :as => :priv_or_pub_customer, :dependent => :destroy
def method_missing( symbol, *args )
self.corporate_customer.send( symbol, *args )
end
end
class PublicCustomer < ActiveRecord::Base
has_one :corporate_customer, :as => :priv_or_pub_customer, :dependent => :destroy
def method_missing( symbol, *args )
self.corporate_customer.send( symbol, *args )
end
end
我没有测试过这段代码(甚至检查了它的语法)。相反,它只是为了指向多态关系的方向。
重写method_missing以调用嵌套对象可以保存编写代码,如
my_public_customer.corporate_customer.account.some_attribute
而你可以写
my_public_customer.some_attribute
回应评论:
问题是像“是一个”,“有很多”和“属于”这样的概念都是由关系模型中的外键关系实现的。继承的概念与RDB系统完全不同。这些关系的语义必须通过您选择的ORM技术映射到关系模型上。
但是Rails的ActiveRecord库并没有将“is_a”实现为模型之间的关系。
有几种方法可以在RDB中为类层次结构建模。
所有帐户的单个表但具有冗余属性 - ActiveRecord只需在表格中添加“类型”列即可支持此功能。然后像这样创建类层次结构:
class Account < ActiveRecord::Base
class GovernmentCustomer < Account
class CorporateCustomer < Account
class PublicCustomer < CorporateCustomer
class PrivateCustomer < CorporateCustomer
然后,如果你调用PrivateCustomer.new,类型字段将自动设置为“PrivateCustomer”,当你调用Account.find时,返回的对象将是正确的类。
这是我推荐的方法,因为它是迄今为止最简单的方法。
每个具体类的一个表 - 据我所知,在ActiveRecord中没有为此提供映射。此方法的主要问题是获取所有帐户的列表,您必须加入三个表。需要的是某种主索引,它导致下一个模型。
每个类的一个表 - 您可以将表示抽象类的表视为一种统一索引,或存储在具体类的表中的对象目录。通过这种方式考虑,你将is_a关系改为has_a关系,例如对象has_a index_entry和index_entry属于对象。这可以通过ActiveRecord使用多态关系进行映射。
本书[{3}}(从第2版第341页开始)对这个问题进行了很好的讨论。
答案 1 :(得分:0)
搜索ActiveRecord Single Table Inheritance功能。 很遗憾,我无法在网上找到更详细的参考链接。我读到的最详细的解释来自“The Rails Way”一书。
答案 2 :(得分:0)
这是这样做的一种方式(最简单):
class Account < ActiveRecord::Base
self.abstract_class = true
has_many :corporate_customers
has_many :government_customers
end
class CorporateCustomer < ActiveRecord::Base
self.abstract_class = true
belongs_to :account
has_many :private_customers
has_many :public_customers
end
class PrivateCustomer < ActiveRecord::Base
belongs_to :corporate_customer
end
class PublicCustomer < ActiveRecord::Base
belongs_to :corporate_customer
end
class GovernmentCustomer < ActiveRecord::Base
belongs_to :account
end
注意:抽象模型是不能拥有对象(无法实例化)的模型,因此它们也没有关联的表。如果你想拥有表,那么我就无法理解它为什么需要一个抽象类。
答案 3 :(得分:0)
假设大多数数据是共享的,您只需要一个表:帐户。这将起作用,假设帐户有一个字符串类型列。
class Account < ActiveRecord::Base
self.abstract_class = true
end
class CorporateCustomer < Account
self.abstract_class = true
has_many financial_statements
end
class PrivateCustomer < CorporateCustomer
end
class PublicCustomer < CorporateCustomer
end
class GovernmentCustomer < Account
end
Google for Rails STI,特别是Rails STI摘要,以获取更多有用信息。