使用mixin修改ActiveRecord验证

时间:2013-07-19 11:56:36

标签: ruby-on-rails

我有一个ActiveRecord mixin(我想你可以称之为?),它为这些模型添加了各种默认范围和回调,以便对多租户查询进行范围化。

我还希望能够修改该模型上现有的唯一性验证以包含范围。我发现我可以使用Model.validators查看所有验证,所以我自然会尝试修改范围选项,如下所示:

Model.validators
  .select{|v| v.is_a?(ActiveRecord::Validations::UniquenessValidator)}
  .map{|v| v.options[:scope] = :client_id }

..但是,对于RuntimeError: can't modify frozen Hash哈希,这会导致错误options。谁知道我怎么能这样做?我知道它可能会涉及一些非常糟糕的代码。

如果编辑它是不可能的,我可以覆盖它或抓住它吗?

编辑 - 我发现this,这几乎就是我想要做的但是它在Rails 3.2中不起作用,我认为它们完全改变了验证的存储方式?任何人都可以帮助我/给我指点如何在Rails 3中使用它?

1 个答案:

答案 0 :(得分:0)

最后破解了它。关键是_validate_callbacks

def scope_validators(foreign_key)
  new_callback_chain = self._validate_callbacks.reject do |callback|
    callback.raw_filter.is_a?(ActiveRecord::Validations::UniquenessValidator)
  end
  deleted = self._validate_callbacks - new_callback_chain
  (self._validate_callbacks.clear << new_callback_chain).flatten!
  deleted.each do |c|
    v = c.raw_filter
    v.attributes.each do |a|
      validates_uniqueness_of *v.attributes, v.options.merge(scope: foreign_key)
    end
  end
end

就像混合在模特中的一种享受。