删除或覆盖由超类或 mixin 添加的 ActiveRecord 验证 [英] Removing or overriding an ActiveRecord validation added by a superclass or mixin

查看:36
本文介绍了删除或覆盖由超类或 mixin 添加的 ActiveRecord 验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Rails 应用程序中使用 Clearance 进行身份验证.Clearance::User mixin 向我的 User 模型添加了一些验证,但我想删除或覆盖其中的一个.这样做的最佳方法是什么?

I'm using Clearance for authentication in my Rails application. The Clearance::User mixin adds a couple of validations to my User model, but there's one of these that I would like to remove or override. What is the best way of doing this?

有问题的验证是

validates_uniqueness_of :email, :case_sensitive => false

这本身还不错,但我需要添加 :scope =>:account_id.问题是,如果我将它添加到我的 User 模型

which in itself isn't bad, but I would need to add :scope => :account_id. The problem is that if I add this to my User model

validates_uniqueness_of :email, :scope => :account_id

我得到了两个验证,并且 Clearance 添加的一个比我的限制更多,所以我的无效.我需要确保只有我的运行.我该怎么做?

I get both validations, and the one Clearance adds is more restrictive than mine, so mine has no effect. I need to make sure that only mine runs. How do I do this?

推荐答案

我最终通过以下技巧解决"了这个问题:

I ended up "solving" the problem with the following hack:

  1. :email 类型的 :taken
  2. 属性上查找错误
  3. 检查此帐户的电子邮件是否唯一(这是我想做的验证)
  4. 如果此帐户的电子邮件是唯一的,则删除错误.

在您阅读代码并发现我如何消除错误之前,这听起来很合理.ActiveRecord::Errors 一旦添加了错误,就没有方法可以消除错误,所以我必须掌握它的内部结构并自己完成.超级骗子超级丑.

Sounds reasonable until you read the code and discover how I remove an error. ActiveRecord::Errors has no methods to remove errors once added, so I have to grab hold of it's internals and do it myself. Super duper mega ugly.

这是代码:

def validate
  super
  remove_spurious_email_taken_error!(errors)
end

def remove_spurious_email_taken_error!(errors)
  errors.each_error do |attribute, error|
    if error.attribute == :email && error.type == :taken && email_unique_for_account?
      errors_hash = errors.instance_variable_get(:@errors)
      if Array == errors_hash[attribute] && errors_hash[attribute].size > 1
        errors_hash[attribute].delete_at(errors_hash[attribute].index(error))
      else
        errors_hash.delete(attribute)
      end
    end
  end
end

def email_unique_for_account?
  match = account.users.find_by_email(email)
  match.nil? or match == self
end

如果有人知道更好的方法,我将不胜感激.

If anyone knows of a better way, I would be very grateful.

这篇关于删除或覆盖由超类或 mixin 添加的 ActiveRecord 验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆