Modèles nesteds et validation parente

J’ai deux modèles.
Parent has_many Children ;
Parent accepte_nested_atsortingbutes_for Children ;

 class Parent  :destroy accepts_nested_atsortingbutes_for :children, :allow_destroy => true validates :children, :presence => true end class Child < ActiveRecord::Base belongs_to :parent end 

J’utilise la validation pour valider la présence d’enfants pour chaque parent, donc je ne peux pas sauver un parent sans enfants.

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

travaux de validation. Ensuite, nous allons détruire les enfants via l’atsortingbut _destroy :

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

donc je peux détruire tous les enfants via des formulaires nesteds et la validation passera.

En fait, cela se produit car après avoir supprimé child de mon parent via _delete , la méthode children renvoie toujours l’object détruit avant de le recharger, donc la validation a réussi:

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

Est-ce un bug?

Quelle est la question. La question est la meilleure solution pour le réparer. Mon approche consiste à append le filtre before_destroy à Child pour vérifier s’il s’agit du dernier. Mais cela rend le système compliqué.

Cela fonctionnera probablement pour vous, mais j’ai l’impression que la réponse est bien meilleure. Cela ressemble à un bug pour moi.

 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 

Ce n’est pas un bug. Selon la documentation

Valide que les atsortingbuts spécifiés ne sont pas vides (comme défini par l’object # vide?)

et validates :children, :presence => true est la même chose. La documentation ne dit pas ce qui se passe si vous essayez de l’utiliser sur une association. Vous devez utiliser la validation personnalisée en utilisant validate .

Utilisation de validates_presence_of sur has_many appels d’appels blank? sur les children association, qui est un object de la classe Array. Depuis le blank? n’est pas défini pour un Array , il déclenche method_missing qui est pris dans Rails. Habituellement, il fait ce que vous voulez, mais j’ai trouvé que cela échouait dans Rails 3.1rc et Ruby 1.8.7. Il m’a fallu deux heures pour savoir ce qui se passait.