rails index home generate create ruby-on-rails validates-associated

ruby-on-rails - create - rails generate controller home index



¿Mejor valida el método asociado para Rails 3? (4)

Rails 3 incluye validates_associated que se llama automáticamente al guardar un modelo anidado. El problema con el método es que el mensaje es terrible: "Los modelos no son válidos"

Ha habido algunas publicaciones atacando este problema para Rails 2:

y probablemente hay más. Sería genial tener una versión mejor como se describe en estas publicaciones que sea compatible con Rails 3. La mejora principal sería incluir por qué falla el modelo asociado.


En la relación, puede usar :autosave => true lugar, que intentará guardar los modelos secundarios cuando guarde el padre. Esto ejecutará automáticamente las validaciones de los hijos e informarán con los mensajes de error adecuados.

Además, si agrega una validación de presencia en el hijo que el padre debe configurarse y construye los objetos secundarios a través de la asociación, ni siquiera necesita la autosave y aparece un hermoso mensaje de error. Por ejemplo:

class Trip < ActiveRecord::Base validates :name, :presence => true attr_accessible :name has_many :places, dependent: :destroy, :inverse_of => :trip end class Place < ActiveRecord::Base belongs_to :trip validates :name, :trip, presence: true attr_accessible :name end

Luego puedes obtener un buen mensaje de error con el siguiente escenario de uso:

> trip = Trip.new(name: "California") => #<Trip id: nil, name: "California"> > trip.places.build => #<Place id: nil, name: nil, trip_id: nil> > trip.valid? => false > trip.errors => #<ActiveModel::Errors:0x00000004d36518 @base=#<Trip id: nil, name: "California">, @messages={:places=>["is invalid"]}> > trip.errors[:places] => ["is invalid"]

Creo que validates_associated es una reliquia de la era anterior a la salvación automática de niños y ya no es la mejor manera de hacer las cosas. Por supuesto que no está necesariamente bien documentado. No estoy 100% seguro de que esto también se aplique a Rails 2.3, pero tengo la sensación de que sí. Estos cambios se produjeron cuando se agregó la característica de atributos anidados (que fue en algún momento en 2.x).

Este es un fragmento simplificado de código de un proyecto de capacitación que publiqué en github .


Estaba teniendo este problema, y ​​al final utilicé la solución dada aquí por Ben Lee :

valida asociado con el mensaje de error del modelo

Ben dice:

Puede escribir su propio validador personalizado, basado en el código del validador incorporado.

Al buscar el código fuente de validates_associated, vemos que usa el "AssociatedValidator". El código fuente para eso es:

module ActiveRecord module Validations class AssociatedValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) return if (value.is_a?(Array) ? value : [value]).collect{ |r| r.nil? || r.valid? }.all? record.errors.add(attribute, :invalid, options.merge(:value => value)) end end module ClassMethods def validates_associated(*attr_names) validates_with AssociatedValidator, _merge_attributes(attr_names) end end end end

Así que puedes usar esto como un ejemplo para crear un validador personalizado que burbujee mensajes de error como este:

module ActiveRecord module Validations class AssociatedBubblingValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) (value.is_a?(Array) ? value : [value]).each do |v| unless v.valid? v.errors.full_messages.each do |msg| record.errors.add(attribute, msg, options.merge(:value => value)) end end end end end module ClassMethods def validates_associated_bubbling(*attr_names) validates_with AssociatedBubblingValidator, _merge_attributes(attr_names) end end end end

Puede poner este código en un inicializador, algo así como /initializers/associated_bubbling_validator.rb .

Finalmente, lo validarías así:

class User < ActiveRecord::Base validates_associated_bubbling :account end

NOTA: el código anterior no se ha probado completamente, pero si no funciona del todo, es de esperar que sea suficiente para ponerlo en el camino correcto



validates_associated ejecuta las validaciones especificadas en la clase del objeto asociado. Los errores en el nivel de clase principal simplemente dicen "mi hijo no es válido". Si desea los detalles, exponga los errores en el objeto secundario (a nivel de la forma del niño en la vista).