38

有什么方法可以验证 Rails 中的单个属性?

就像是:

ac_object.valid?(attribute_name)
4

4 回答 4

46

有时会有相当昂贵的验证(例如,需要执行数据库查询的验证)。在这种情况下,您需要避免使用valid?,因为它的功能远远超出您的需要。

有一个替代解决方案。可以使用的validators_on方法ActiveModel::Validations

validators_on(*attributes) 公共

列出所有用于验证特定属性的验证器。

根据它您可以手动验证您想要的属性

例如,我们只想验证titleof Post

class Post < ActiveRecord::Base

  validates :body, caps_off: true 
  validates :body, no_swearing: true
  validates :body, spell_check_ok: true

  validates presence_of: :title
  validates length_of: :title, minimum: 30
end

哪里no_swearingspell_check_ok是极其昂贵的复杂方法。

我们可以做到以下几点:

def validate_title(a_title)
  Post.validators_on(:title).each do |validator|
    validator.validate_each(self, :title, a_title)
  end
end

这将仅验证 title 属性而不调用任何其他验证。

p = Post.new
p.validate_title("")
p.errors.messages
#=> {:title => ["title can not be empty"]

笔记

我不完全相信我们应该validators_on安全使用,所以我会考虑在validates_title.

于 2014-11-20T18:42:48.563 回答
45

您可以在模型中实现自己的方法。像这样的东西

def valid_attribute?(attribute_name)
  self.valid?
  self.errors[attribute_name].blank?
end

或将其添加到ActiveRecord::Base

于 2011-01-26T12:43:27.577 回答
12

我最终以@xlembouras 的回答为基础,并将此方法添加到我的ApplicationRecord

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def valid_attributes?(*attributes)
    attributes.each do |attribute|
      self.class.validators_on(attribute).each do |validator|
        validator.validate_each(self, attribute, send(attribute))
      end
    end
    errors.none?
  end
end

然后我可以在控制器中做这样的事情:

if @post.valid_attributes?(:title, :date)
  render :post_preview
else
  render :new
end
于 2017-08-11T17:33:22.087 回答
1

基于@coreyward 的回答,我还添加了一个validate_attributes!方法:

class ApplicationRecord < ActiveRecord::Base
  self.abstract_class = true

  def valid_attributes?(*attributes)
    attributes.each do |attribute|
      self.class.validators_on(attribute).each do |validator|
        validator.validate_each(self, attribute, send(attribute))
      end
    end
    errors.none?
  end

  def validate_attributes!(*attributes)
    valid_attributes?(*attributes) || raise(ActiveModel::ValidationError.new(self))
  end
end
于 2021-04-05T14:16:24.680 回答