6

我有一个“事务”(扩展 ActiveRecord::Base)。我有两种不同类型的交易,“购买”或“捐赠”。两者之间有足够的重叠,不需要创建两个单独的数据库表,所以我只有一个表用于带有“item_type”列的事务。

但是,购买和捐赠有不同的方法和验证,因此将它们分成两个不同的控制器和模型是有意义的。我没有创建 ActiveBase 模型(减去表格),而是尝试为每个模型使用模块。

这是购买模块的样子。

module Purchase
  def self.included(base)
    base.validates :amount, 
      :presence => true
  end

  def testing
    "testing"
  end
end

下面是如何创建一个:(此代码在 Purchases 控制器的创建操作中)

@purchase = Transaction.new(params[:purchase]).extend(Purchase)

我可以调用@purchase.testing 并返回“测试”。但是,该验证并未运行。

如果我在交易模型中以传统方式包含模块,并带有“包含购买”,那么它们就可以工作。

有什么想法可以让这个工作流程发生吗?我遵循了一点: http: //paulsturgess.co.uk/articles/84-how-to-include-class-and-validation-methods-using-a-module-in-ruby-on-rails

4

2 回答 2

5

如果您只想处理单表和多列,我认为首选方法是单表继承。如果您搜索单表继承,您可以在此处阅读相关内容。不过,关于您的问题,关于如何包含模块,我认为您希望将模块包含在元类中,@purchase以便它不会包含在所有后续事务中。有点像这样(绝对可以缩短):

@purchase = Transaction.new(params[:purchase])
class << @purchase
  include Purchase
end

然后,您的验证应该有效。

于 2012-07-06T21:01:42.467 回答
3

当你这样做时,你的included钩子不会运行.extend(Purchase)。你需要一个extended钩子。在extended钩子内部,您可以在新对象的特征类上调用 Rails 验证助手Transaction(类似于 @Adam 演示的内容)。

于 2012-07-06T21:41:30.687 回答