有没有办法验证ActiveRecord上的特定属性而不首先实例化对象?

时间:2009-01-19 10:58:00

标签: ruby-on-rails ruby validation activerecord

例如,如果我有一个用户模型并且我只需要验证登录(这可以通过ajax验证表单时发生),那么如果我使用User模型中定义的相同模型验证而不实际实例化将会很棒用户实例。

所以在控制器中我可以编写像

这样的代码
User.valid_attribute?(:login, "login value")

无论如何我能做到吗?

8 个答案:

答案 0 :(得分:20)

由于验证在实例上运行(并且它们使用实例的errors属性作为错误消息的容器),因此如果没有实例化对象,则无法使用它们。话虽如此,您可以将此需要的行为隐藏到类方法中:

class User < ActiveRecord::Base
  def self.valid_attribute?(attr, value)
    mock = self.new(attr => value)
    unless mock.valid?
      return mock.errors.has_key?(attr)
    end
    true
  end
end

现在,您可以致电

User.valid_attribute?(:login, "login value")

就像你想要的那样。

(理想情况下,您将该类方法直接包含在ActiveRecord :: Base中,以便每个模型都可以使用它。)

答案 1 :(得分:5)

感谢米兰的建议。受它的启发,我创建了一个简单的模块,可用于将此功能添加到任何类。请注意,原始Milans建议的逻辑错误为:

return mock.errors.has_key?(attr)

显然应该是:

return (not mock.errors.has_key?(attr))

我已经测试了我的解决方案,它应该可以工作,但是我不能保证。这是我光荣的解决方案。如果你拿走模块的东西,基本上是一个2线程..它接受方法名称作为咒语或符号。

module SingleAttributeValidation

  def self.included(klass)
    klass.extend(ClassMethods)
  end

  module ClassMethods
    def valid_attribute?(attr, value)
      mock = self.new(attr => value)
      (not mock.valid?) && (not mock.errors.has_key?(attr.class == Symbol ? attr : attr.to_sym))
    end
  end
end

答案 2 :(得分:3)

使用标准验证程序:


User.new(:login => 'login_value').valid?

如果这对您不起作用,请为此构建自定义类方法:


class User < ActiveRecord::Base

  validate do |user|
    user.errors.add('existing') unless User.valid_login?(user.login)
  end

  def self.valid_login?(login)
    # your validation here
    !User.exist?(:login=> login)
  end
end

答案 3 :(得分:2)

我有一段时间在Rails 3.1中使用它。这终于奏效了。 (不确定这是否是最好的方式,我有点新手。)我遇到的问题是该值被设置为键入ActiveSupport :: SafeBuffer,并且验证失败。

def self.valid_attribute?(attr, value)
  mock = User.new(attr => "#{value}") # Rails3 SafeBuffer messes up validation
  unless mock.valid?
    return (not mock.errors.messages.has_key?(attr))
  end
  return true
end

答案 4 :(得分:1)

我已经使用了自定义类解决方案,但我只是想确保没有更好的方法

class ModelValidator
  def self.validate_atrribute(klass, attribute, value)
    obj = Klass.new
    obj.send("#{attribute}=", value)
    obj.valid?
    errors = obj.errors.on(attribute).to_a
    return (errors.length > 0), errors 
  end
end

我可以像

一样使用它

有效,错误= ModelValidator.validate_attribute(用户,“登录”,“humanzz”)

答案 5 :(得分:0)

class User < ActiveRecord::Base
  validates_each :login do |record, attr, value|
    record.errors.add attr, 'error message here' unless User.valid_login?(value)
  end

  def self.valid_login?(login)
    # do validation
  end
end

只需调用User.valid_login?(登录)即可查看登录本身是否有效

答案 6 :(得分:0)

您建议的'valid_attribute'方法的实现:

class ActiveRecord:Base
  def self.valid_attribute?(attribute, value)
    instance = new
    instance[attribute] = value
    instance.valid?

    list_of_errors = instance.errors.instance_variable_get('@errors')[attribute]

    list_of_errors && list_of_errors.size == 0
  end
end

答案 7 :(得分:0)

怎么样:

User.columns_hash.has_key?( '登录')