Pregunta

¿Si hay una forma en que pueda validar un atributo único en los rieles?

Algo como:

ac_object.valid?(attribute_name)

Lo usaré para la validación de AJAX de campos de modelos particulares. Mover estas validaciones al JavaScript hace que el código sea realmente feo.

¿Fue útil?

Solución

Puede implementar su propio método en su modelo. Algo como esto

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

O agregarlo a ActiveRecord::Base

Otros consejos

A veces hay validaciones que son bastante caras (por ejemplo, validaciones que necesitan realizar consultas de bases de datos). En ese caso, debe evitar usar valid? Porque simplemente hace mucho más de lo que necesitas.

Hay una solución alternativa. Puedes usar el validators_on método de ActiveModel::Validations.

Validators_on (*atributos) público

Enumere todos los validadores que se están utilizando para validar un atributo específico.

según el cual puede validar manualmente los atributos que desea

por ejemplo, solo queremos validar el title de 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

Dónde no_swearing y spell_check_ok son métodos complejos que son extremadamente caros.

Podemos hacer lo siguiente:

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

que validará solo el atributo de título sin invocar otras validaciones.

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

Nota

No estoy completamente seguro de que se supone que debemos usar validators_on Safamente, por lo que consideraría manejar una excepción de manera sensata en validates_title.

Terminé construyendo la respuesta de @xlembouras y agregué este método a mi 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

Entonces puedo hacer cosas como esta en un controlador:

if @post.valid_attributes?(:title, :date)
  render :post_preview
else
  render :new
end
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top