39 votos

Modelos anidados y de los padres de validación

Tengo dos modelos.
- Parent has_many Children;
- Parent accepts_nested_attributes_for Children;

class Parent < ActiveRecord::Base
  has_many :children, :dependent => :destroy
  accepts_nested_attributes_for :children, :allow_destroy => true
  validates :children, :presence => true
end

class Child < ActiveRecord::Base
  belongs_to :parent
end

Yo uso la validación para validar la presencia de niños para todos los padres, así que no puedo guardar los padres sin hijos.

parent = Parent.new :name => "Jose"
parent.save
#=> false
parent.children_attributes = [{:name => "Pedro"}, {:name => "Emmy"}]
parent.save
#=> true

la validación de las obras. A continuación, vamos a destruir a los niños a través de la _destroy atributo:

parent.children_attributes = {"0" => {:id => 0, :_destroy => true}}
parent.save
#=> true !!!
parent.reload.children
#=> []

así que puede destruir a todos los niños a través de los formularios anidados y validación de pasar.

En realidad eso sucede porque después de eliminar hijo de mi padre a través de la _delete, los niños método devuelve destruido objeto antes de volver a cargarlo, por lo que la validación del pasado:

parent.children_attributes = {"0" => {:id => 0, :_destroy => true}}
parent.save
#=> true !!!
parent.children
#=> #<Child id:1 ...> # It's actually deleted
parent.reload.children
#=> []

Es bug?

¿Cuál es la pregunta. La pregunta es la mejor solución para la reparación. Mi enfoque es agregar before_destroy filtro a Child , para comprobar si es la última. Pero hace que el sistema complicado.

59voto

John Douthat Puntos 28189

Esto probablemente va a funcionar para usted, pero tengo la sensación de que hay una mucho mejor respuesta fuera no. Suena como un error para mí.

class Parent
  validate :must_have_children

  def must_have_children
    if children.empty? or children.all? {|child| child.marked_for_destruction? }
      errors.add(:base, 'Must have at least one child')
    end
  end
end

0voto

Tomáš K. Puntos 1

No es un error. De acuerdo a la documentación

Se valida que el especificado los atributos no son en blanco (como se define por Objeto#en blanco?)

y validates :children, :presence => true es sólo el de la misma. La documentación no dice qué sucede si se intenta utilizar en una asociación. Usted debe utilizar una validación personalizada utilizando validate.

El uso de validates_presence_of a has_many asociación convoca blank? sobre la asociación children, que es un objeto de la clase Array. Desde la blank? no está definido para un Array, se desencadena method_missing que es atrapado en el interior de los Rieles. Generalmente es hacer lo que usted quiere que, pero he encontrado un error en Rails 3.1 rc y Ruby 1.8.7 en una terrible manera: en silencio, revierte los cambios de los registros asociados. Me tomó un par de horas para averiguar lo que está pasando.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X