Rails ActiveRecord: validate single attribute

坚强是说给别人听的谎言 提交于 2019-12-20 16:21:21

问题


If there is a way I can validate single attribute in Rails?

Something like:

ac_object.valid?(attribute_name)

I'm gonna use it for AJAX validation of particular model fields. Moving these validations to the Javascript makes code really ugly.


回答1:


You can implement your own method in your model. Something like this

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

Or add it to ActiveRecord::Base




回答2:


Sometimes there are validations that are quite expensive (e.g. validations that need to perform database queries). In that case you need to avoid using valid? because it simply does a lot more than you need.

There is an alternative solution. You can use the validators_on method of ActiveModel::Validations.

validators_on(*attributes) public

List all validators that are being used to validate a specific attribute.

according to which you can manually validate for the attributes you want

e.g. we only want to validate the title of 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

Where no_swearing and spell_check_ok are complex methods that are extremely expensive.

We can do the following:

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

which will validate only the title attribute without invoking any other validations.

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

note

I am not completely confident that we are supposed to use validators_on safely so I would consider handling an exception in a sane way in validates_title.




回答3:


I wound up building on @xlembouras's answer and added this method to my 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

Then I can do stuff like this in a controller:

if @post.valid_attributes?(:title, :date)
  render :post_preview
else
  render :new
end


来源:https://stackoverflow.com/questions/4804591/rails-activerecord-validate-single-attribute

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!