如何在多代模块中定义/附加rails验证

时间:2010-12-02 19:41:12

标签: ruby-on-rails validation inheritance module

我找到了一种方法来完成这项工作,但我对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没有那么大改变。

1 个答案:

答案 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