我有一个“事务”(扩展了ActiveRecord :: Base)。我有两种不同类型的交易,即“购买”或“捐赠”。两者之间有足够的重叠,因此不需要创建两个单独的数据库表,因此我只有一个表用于具有“item_type”列的事务。
但是,购买和捐赠有不同的方法和验证,因此将它们分成两个不同的控制器和模型是有意义的。我没有创建ActiveBase模型(减去表格),而是试图为每个模型使用模块。
以下是Purchase模块的外观。
module Purchase
def self.included(base)
base.validates :amount,
:presence => true
end
def testing
"testing"
end
end
以下是创建一个的方法:(此代码位于Purchases控制器的create操作中)
@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
答案 0 :(得分:5)
如果您只想使用单个表和多个列,我认为首选方法是单表继承。如果搜索单表继承,可以阅读它here。但是,关于如何包含模块的问题,我认为您希望将模块包含在@purchase
的元类中,因此它不包含在所有后续事务中。有点像这样(绝对可以缩短):
@purchase = Transaction.new(params[:purchase])
class << @purchase
include Purchase
end
然后,您的验证应该有效。
答案 1 :(得分:3)
执行included
时,您的.extend(Purchase)
挂钩将无法运行。你需要一个extended
钩子。在extended
钩子内部,您可以在新Transaction
对象的本征类上调用Rails验证助手(类似于@Adam演示的那样)。