Rails ActiveRecord:验证单个属性

时间:2011-01-26 12:33:19

标签: ruby-on-rails validation rails-activerecord

如果有办法我可以在Rails中验证单个属性吗?

类似的东西:

ac_object.valid?(attribute_name)

我将把它用于特定模型字段的AJAX验证。将这些验证移动到Javascript会使代码变得非常丑陋。

4 个答案:

答案 0 :(得分:37)

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

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

或将其添加到ActiveRecord::Base

答案 1 :(得分:27)

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

还有另一种解决方案。您可以使用ActiveModel::Validations的{​​{3}}方法。

  

validators_on(* attributes)public

     

列出用于验证特定内容的所有验证程序   属性。

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

e.g。我们只想验证title的{​​{1}}:

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_swearing是非常昂贵的复杂方法。

我们可以做到以下几点:

spell_check_ok

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

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

注释

我并不完全相信我们应该安全地使用p = Post.new p.validate_title("") p.errors.messages #=> {:title => ["title can not be empty"] 所以我会考虑在validators_on中以理智的方式处理异常。

答案 2 :(得分:4)

我在@ 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

答案 3 :(得分:0)

基于@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