Подтвердить что ты не робот

Rails ActiveRecord: проверка одного атрибута

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

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

ac_object.valid?(attribute_name)

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

4b9b3361

Ответ 1

Вы можете реализовать свой собственный метод в своей модели. Что-то вроде этого

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

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

Ответ 2

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

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

validators_on (* attributes) 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"]

примечание

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

Ответ 3

Я закончил работу над ответом @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

Ответ 4

Мне нравится решение @coreyward и внес некоторые изменения. Вот что я использую:

приложение/модель/проблемы/attribute_validator.rb

module AttributeValidator
  extend ActiveSupport::Concern

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

Использование:

приложение/модели/user.rb

include AttributeValidator

def something
  do_something if attributes_valid?(:email)
end