【问题标题】:Modifying ActiveRecord Validations with mixin使用 mixin 修改 ActiveRecord 验证
【发布时间】:2013-07-19 11:56:36
【问题描述】:

我有一个 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 中使用它吗?

【问题讨论】:

  • 这肯定是有原因的,为什么该哈希被冻结,但如果 #options=# 设置器可访问,您可以复制哈希。或合并和覆盖 (options = options.merge(...))
  • 哦,那map 没有意义,它返回一个数组[:client_id, :client_id, ...]each 替换它
  • NoMethodError: undefined method 'options=' for #<ActiveRecord::Validations::UniquenessValidator:0x007f9b0531ad88> :(
  • 然后我会尝试删除该验证器并“重新创建”它
  • 我似乎根本无法改变该数组。用一个方便的链接更新了我的问题。

标签: ruby-on-rails


【解决方案1】:

终于破解了。关键是_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

就像混在模型中的款待一样。

【讨论】:

    猜你喜欢
    • 2011-01-19
    • 2011-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多