Ruby on rails Monkey patch Rails UniquenessValidator支持条件
在我的Rails 3.2.11应用程序中,我需要唯一性验证器来支持条件,以便忽略软删除记录。在GitHub上,我发现有一个拉请求正在这样做(https://github.com/rails/rails/pull/5321)但是这个特性似乎不是当前Rails版本的一部分。现在我为UniquenessValidator类创建了一个补丁,如下所示:Ruby on rails Monkey patch Rails UniquenessValidator支持条件,ruby-on-rails,ruby,validation,monkeypatching,Ruby On Rails,Ruby,Validation,Monkeypatching,在我的Rails 3.2.11应用程序中,我需要唯一性验证器来支持条件,以便忽略软删除记录。在GitHub上,我发现有一个拉请求正在这样做(https://github.com/rails/rails/pull/5321)但是这个特性似乎不是当前Rails版本的一部分。现在我为UniquenessValidator类创建了一个补丁,如下所示: module UniquenessValidatorExtension def build_relation(klass, table, attrib
module UniquenessValidatorExtension
def build_relation(klass, table, attribute, value)
relation = super
relation.merge!(options[:conditions]) if options[:conditions]
relation
end
end
ActiveRecord::Validations::UniquenessValidator.send :include, UniquenessValidatorExtension
为了加载它,我创建了一个初始值设定项。问题是,我的方法从未被调用。我做错了什么
下面是指向当前UniquenessValidator类的链接:如果从未调用该方法,则意味着您已在ActiveRecord::Base“必需”之后包含模块。在以下情况之前尝试将其包括在内:
config.before_initialize do
ActiveRecord::Validations::UniquenessValidator.send :include, UniquenessValidatorExtension
end
这就是
include
的工作原理:
module M; end
class C
include M
end
C.ancestors # => [C, M, Object, Kernel, BasicObject]
因此,在您的示例中,将调用来自原始类的方法build\u relation
。JFYI,Ruby 2.0中有prepend
方法:
class C1
prepend M
end
C1.ancestors # => [M, C1, Object, Kernel, BasicObject]
因此,在您的案例中,将从模块中调用方法build\u relation
好的,现在您可以重新打开
uniquenessvalidater
并覆盖整个build\u relationship这个问题是由@nash解释的,但是由于我使用Ruby 1.9.x,这不是一个解决方案。为了让它工作,我给原始方法加了别名,然后替换了它。现在,我能够从覆盖方法调用别名方法
class ActiveRecord::Validations::UniquenessValidator < ActiveModel::EachValidator
alias_method :build_relation_orig, :build_relation
def build_relation(klass, table, attribute, value)
relation = self.build_relation_orig(klass, table, attribute, value)
relation = relation.and(options[:conditions]) if options[:conditions]
relation
end
end
class ActiveRecord::Validations::UniquencesValidator
这正是问题所在。但是由于我使用Ruby 1.9.x,prepend
对我来说不是一个解决方案。我找到了另一种方法,我会在这篇文章的另一个答案中解释这一点。谢谢