Rails ActiveRecord: проверка одного атрибута - PullRequest
29 голосов
/ 26 января 2011

Если есть способ проверить один атрибут в Rails?

Что-то вроде:

ac_object.valid?(attribute_name)

Я собираюсь использовать его для проверки AJAX определенных полей модели. Перемещение этих проверок в Javascript делает код действительно ужасным.

Ответы [ 3 ]

37 голосов
/ 26 января 2011

Вы можете реализовать свой собственный метод в вашей модели.Примерно так

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

Или добавьте его к ActiveRecord::Base

27 голосов
/ 20 ноября 2014

Иногда существуют проверки, которые являются довольно дорогими (например, проверки, которые должны выполнять запросы к базе данных).В этом случае вам нужно избегать использования valid?, потому что он просто делает намного больше, чем вам нужно.

Существует альтернативное решение.Вы можете использовать validators_on метод ActiveModel::Validations.

validators_on (* attribute) public

Список всех валидаторов, которые используются для проверкиконкретный атрибут.

, в соответствии с которым вы можете вручную проверить нужные атрибуты

, например, мы хотим проверить только title из 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 - сложные методы, которые чрезвычайно дороги.

Мы можем сделать следующее:

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"]

note

Я не совсем уверен, что мы должны безопасно использовать validators_on, поэтому я рассмотрел бы обработку исключения в здравом смысле в validates_title.

4 голосов
/ 11 августа 2017

Я основывался на ответе @ 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
...