RoR:STI / MTI / Mixin混乱

时间:2011-03-17 23:06:52

标签: ruby-on-rails model polymorphic-associations mixins sti

我有一个问题,我相信大多数RoR开发人员的基本问题。事实上,它更多的是“理解”而不是真正的编程(我已经编写了一些模块来扩展ActiveRecord :: Base,以便轻松生成与Ext-JS相关的东西而没有任何问题)。

让我们举一个简单的例子,我将用面向ORM的语言而不是数据库/模型语言进行讨论。

  • ThirdParty是一个基本实体,拥有一个名为'label'的公共成员。
  • ThirdParty实例可以是客户,供应商,两者,或者都不是(因此客户/供应商就像具体的接口而不是继承的类)。
  • 客户和供应商都有专门的成员,其中大多数成员对每个相应的类都是唯一的(客户/供应商除了通过ThirdParty绑定的标签字段之外不会共享太多数据)。

我试图做各种事情:

  • ThirdParty<的ActiveRecord ::基
  • 客户<第三方
  • 供应商<第三方

[编辑] 在这里错过了我的解释。我的意思是:ThirdParty的一个实例可以是客户,供应商,BOTH或NONE。 正如第一位评论者指出的那样,我的例子可能不是最好的......你可以用“角色”代替“ThirdParty”,用“Archer”/“SwordsMan”代替“顾客”/“供应商”。字符可以是一个,两个,两个,也可以不是,但可以提供有关Character的任何实例的信息。 Archer / SwordsMan上的getter应该返回Character“实现”接口契约的实例,而不是仅仅在角色对象上返回一个带有“getter”的实例。 [/编辑]

我也尝试过:

  • ThirdParty< ActiveRecord :: Base(has_one Customer; has_one Supplier)
  • 客户< ActiveRecord :: Base(belongs_to ThirdParty)
  • 供应商< ActiveRecord :: Base(belongs_to ThirdParty)

但对我来说这似乎有点“丑陋”,因为我必须做Customer.find(某事).third_party.label来访问我的“接口”“继承”的数据。

另外,我可以在我的ThirdParty模型中包含customer_id和supplier_id字段,但它似乎也不正确,因为一个ThirdParty既可以是,也可以不是......

当然,我希望能够找到一个没有阻碍性/太多黑客攻击的解决方案,允许我为其他模型做一些多态关联(比如一个可寻址的,或可评论,可联系等...)

我也在这样的博客上阅读了很多关于这个主题的文章:http://mediumexposure.com/multiple-table-inheritance-active-record/ ...但我错过了正确的方法(在我发现的大部分文档中目前尚不清楚它是否适用于Rails 1,2,3 ...最近在这个问题上实施了什么,等等。)

有人可以向我提供各种“最新”网站,或者举例说明我给出的例子吗?

通过提前,我感谢大家提出了我的问题,并向我解释了有关这一特定主题的不同技术。

PS:如果你需要我解释一下我正在寻找的东西,我可以试试......但请记住,我的英语在这个领域有点“有限”,因为我对RoR比较新

2 个答案:

答案 0 :(得分:3)

只有一个共同的字段,单个(或多个)表继承可能不是可行的方法。如果你想在类之间共享功能,我会创建一个包含在每个类中的ThirdParty模块:

module ThirdParty
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    # define your shared class methods here
  end

  # define you shared instance methods down here
end

class Customer < ActiveRecord::Base
  include ThirdParty
end

class Supplier < ActiveRecord::Base
  include ThirdParty
end

这允许您定义利用每个包含类的label属性的方法。你提到你希望能够与其他模型接口,可能是多态的。如果所有ThirdParty对象中都存在这些关联,那么您只需在self.included调用(使用instance_eval)或在ClassMethods中设置关联作为方法:

module ThirdParty
  def self.included(base)
    base.extend ClassMethods
    base.instance_eval do
      has_many :buyers, :as => :third_party
    end
  end

  module ClassMethods
    def has_address
      has_one :address, :as => :third_party
      delegate :street, :city, :state, :zip, :to => :address
    end
  end
end

class Supplier < ActiveRecord::Base
  include ThirdParty # this would set up the :buyers association

  has_address # this sets up the address association
end

希望这会有所帮助。关于做这样的事情的更多信息只是google“ruby mixin” - 那里有很多信息。

答案 1 :(得分:1)

我最近分配了一个有希望的项目来在Rails中实现多表继承和类继承。我花了几天时间对它进行快速开发,修复,评论和文档处理,并将其重新发布为CITIER(Rails的类继承和表继承嵌入)。

我认为你可以将它与上面的答案结合起来吗?

考虑一下:http://peterhamilton.github.com/citier

基本上,您可以在ThirdParty类中使用公共字段,并创建继承它们的Customer或Supplier对象。

您可以创建一个模块,其中包含两个功能并在它们之间共享功能吗?

CITIER不允许您同时让第三方成为客户和供应商,因为它依赖于不支持多重继承的Ruby继承。我会想到某种共享模块解决方案会使这部分工作吗?

事实上,CITIER已经使用了类似于上面答案的东西,所以会看到正确的轨道。