我找到了一种方法来完成这项工作,但我对Rails 3方式更好的方式感到好奇。 (我仍在使用2.3.5,但希望在新年期间迁移。)
情况:我有两层模块继承,第二层混合成Rails模型。这两个模块都定义了验证方法,我希望它们都将验证附加到基类,但由于两个级别的继承,以下方法不起作用:
def self.included(base)
base.validate :yadda_yadda
end
当该模块被另一个模块包含时,解释器会因为模块不知道ActiveRecord::Validations
而暂停。包括验证模块的问题是“在哪里save
?”感谢alias_method
。
以下内容有效,只要您忘记在覆盖super
时调用validate()
即可。我不相信自己或未来的维护者会记住这一点,所以我想使用validate :yadda_yadda
成语,如果可能的话。
module Grandpa
def validate
must_be_ok
end
def must_be_ok
errors.add_to_base("#{self} wasn't ok")
end
end
module Dad
include Grandpa
def validate
super
must_be_ok_too
end
def must_be_ok_too
errors.add_to_base("#{self} wasn't ok either")
end
end
class Kid < ActiveRecord::Base
include Dad
validate :must_be_ok_three
def must_be_ok_three
errors.add_to_base("#{self} wasn't ok furthermore")
end
end
连连呢? Rails 3方法提示?我认为验证API没有那么大改变。
答案 0 :(得分:0)
我解决了它(当我遇到同样的问题时,除了验证之外的其他东西)。
简短回答:您可以在要引入的模块上调用send(:included,base)。在更高版本的included()定义中,您需要检查基类是Class还是Module。 / p>
你为什么要这样做?好吧,我有一些模块可以从我的模型中提取一些常用功能。例如,模块HasAllocable
设置多态belongs_to
关系,以及虚拟属性的getter / setter对。现在我有另一个需要引入HasAllocable
的模块,以避免基类不得不记住它。
我有兴趣知道这对任何人都是否有趣。我没有在网上看到类似的东西,所以我想知道多层模型继承是否更像是反模式。
module Grandpa
def self.included(base)
if base.kind_of?(Class)
base.validate :must_be_ok
end
end
end
module Dad
include Grandpa
def self.included(base)
if base.kind_of?(Class)
# you can do this
#base.send(:include, Grandpa)
# you can also do this
Grandpa.send(:included, base)
# this does not invoke Grandpa.included(Kid)
#super(base)
base.validate :must_be_ok_too
end
end
end
class Kid < ActiveRecord::Base
include Dad
validate :must_be_ok_three
end