10

例如,如果我有一个用户模型并且我只需要验证登录(这可能在通过 ajax 验证表单时发生),如果我使用在用户模型中定义的相同模型验证而不实际实例化用户实例,那就太好了.

所以在控制器中我可以编写类似的代码

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

无论如何我可以做到这一点吗?

4

8 回答 8

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 中,这样它就可用于每个模型。)

于 2009-01-19T11:28:31.320 回答
5

谢谢米兰的建议。受此启发,我创建了一个简单的模块,可用于将此功能添加到任何类。请注意,最初的 Milans 建议有一个逻辑错误,如下所示:

return mock.errors.has_key?(attr)

显然应该是:

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

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

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
于 2010-10-26T17:58:08.740 回答
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
于 2009-01-19T11:29:03.347 回答
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
于 2011-10-29T23:46:21.337 回答
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(User, "login", "humanzz")

于 2009-01-19T11:45:25.873 回答
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?(login) 即可查看登录本身是否有效

于 2009-01-19T12:51:44.087 回答
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
于 2009-01-19T13:05:19.533 回答
0

怎么样:

User.columns_hash.has_key?('lo​​gin')

于 2009-02-25T03:27:01.593 回答