【问题标题】:Modules vs. Classes and their influence on descendants of ActiveRecord::Base模块与类及其对 ActiveRecord::Base 后代的影响
【发布时间】:2010-02-22 19:57:02
【问题描述】:

这是一个 Ruby OO 头疼的问题,由这个 Rails 场景带来:

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 定义的方法通过has_many,我会收到一条错误消息,抱怨找不到Book#prices

这是为什么呢? Book 是 Product 的直系后代!

更有趣的是以下..

随着我开发这个层次结构PrintProduct 开始变得更加抽象ActiveRecord::Base,所以我认为重新定义所有内容是谨慎的:

class Product < ActiveRecord::Base
end

class PrintProduct < Product
end

class Book < PrintProduct
end

所有方法定义等都是一样的。但是,在这种情况下,我的 Web 表单不会加载,因为找不到由 attr_accessor 定义的属性(这是表单引用但未保存在数据库中的“虚拟属性”)。我会收到一条错误消息,说没有方法Book#isbn。这是为什么??当PrintProduct 是一个类时,我看不出为什么在我的表单的fields_for 块中找不到attr_accessor 属性,但是当PrintProductModule 时找到它们。

任何见解将不胜感激。我很想知道为什么会发生这些错误!

【问题讨论】:

  • 有想过这个吗?我在我的 rails 3 端口遇到了。

标签: ruby-on-rails ruby oop


【解决方案1】:

PrintProduct 中的attr_accessor 调用延迟到混音时间可能会更好:

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

这个问题可能与 attr_accessor 调用的时间以及它如何应用于混合的模块有关。我不确定时间是由 Ruby 规范定义的,因此它可能会因实现或版本而异.

【讨论】:

  • 当 PrintProduct 是一个模块时,#isbn 的 attr_accessor 声明按预期工作。当 PrintProduct 更改为类时,找不到 #isbn。如果我按照您所说的使用 self.extended 进行操作,也许它会起作用,但这不是问题。我想知道为什么会出现这些错误,因为这两种设计似乎都没有任何“错误”(或者可能有,这就是错误发生的原因)。总之,谢谢你的回答!
猜你喜欢
  • 1970-01-01
  • 2013-10-08
  • 1970-01-01
  • 2014-04-11
  • 2016-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多