2

假设我有 5 张桌子。ActiveRecord 可以处理这个吗?你会如何设置它?

层次结构:

Account (Abstract)
  CorporateCustomer (Abstract)
    PrivateCustomer
    PublicCustomer
  GovernmentCustomer

编辑:在休眠和城堡活动记录中,启用此场景所需的方法称为“加入子类”。

4

4 回答 4

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 belongs_to 对象。这可以由 ActiveRecord 使用多态关系映射。

在《Agile Web Development with Rails》一书中对这个问题有很好的讨论 (从第 2 版的第 341 页开始)

于 2009-06-20T12:25:34.290 回答
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

注意:抽象模型是不能有对象(不能被实例化)的模型,因此它们也没有关联的表。如果你想有表,那么我不明白为什么它需要一个抽象类。

于 2009-06-19T16:04:04.503 回答
0

搜索 ActiveRecord单表继承功能。不幸的是,我无法在网上找到更详细的参考链接。我读到的最详细的解释来自“The Rails Way”一书。

于 2009-06-19T14:00:00.293 回答
0

假设大部分数据是共享的,您只需要一张表:accounts。假设帐户具有字符串类型列,这将起作用。

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 摘要,以获得更多有用的信息。

于 2009-06-19T17:26:05.750 回答