模块与类及其对ActiveRecord :: Base后代的影响

时间:2010-02-22 19:57:03

标签: ruby-on-rails ruby oop

以下是这个Rails场景带来的Ruby OO主要问题:

class Product < ActiveRecord::Base
  has_many(:prices)
  # define private helper methods 
end

module PrintProduct
  attr_accessor(:isbn)
  # override methods in ActiveRecord::Base
end

class Book < Product
  include PrintProduct
end

Product是所有产品的基类。书籍通过STI保存在products表中。 PrintProduct模块为Product的后代带来了一些常见的行为和状态。 Book在视图中的fields_for块内使用。这对我有用,但我发现了一些奇怪的行为:

  • 表单提交后,在我的控制器中,如果我在PrintProduct中定义的书上调用方法,并且该方法调用Product中定义的辅助方法,后者又调用{由prices定义的{1}}方法,我会收到错误,抱怨找不到has_many

为什么?本书是产品的直系后代!

更有趣的是以下......

当我开发这个层次结构时Book#prices开始变得更加抽象PrintProduct,所以我认为重新定义所有内容是谨慎的:

ActiveRecord::Base

所有方法定义等都相同。但是,在这种情况下,我的Web表单将不会加载,因为找不到class Product < ActiveRecord::Base end class PrintProduct < Product end class Book < PrintProduct end 定义的属性(由表单引用但未在DB中保留的“虚拟属性”)。我会收到错误消息,说没有方法attr_accessor。这是为什么??当Book#isbn是一个类时,我看不出在attr_accessor块中找不到fields_for属性的原因,但是当PrintProduct是{PrintProduct时找到它们{1}}。

任何见解都将受到赞赏。我很想知道为什么会发生这些错误!

1 个答案:

答案 0 :(得分:0)

您可能会更好地延迟attr_accessor PrintProduct来电,直到混音时间:

module PrintProduct
  def self.included(base)
    base.attr_accessor :isbn
  end
  # other instance methods here
end

问题可能与attr_accessor调用的时间有关,以及它如何适用于混合的模块。我不确定时序是由Ruby规范定义的,因此它可能会在实现之间发生变化或版本。