Question

Pour être plus précis, "Comment puis-je valider qu'un modèle nécessite la création d'au moins x modèles associés valides?" . J'essaie de valider les modèles imbriqués créés sous la même forme que le parent (et affichent en fin de compte les validations immédiates à la jQuery). En tant qu’exemple courant, supposons les modèles et schémas suivants:

class Project
  include DataMapper::Resource

  property :id,     Serial
  property :title,  String, :nullable => false

  has 2..n, :tasks
end

class Task
  include DataMapper::Resource

  property :id,         Serial
  property :project_id, Integer,  :key => true
  property :title,      String,   :nullable => false

  belongs_to :project
end

Toutes les validations sont effectuées dans les définitions de schéma, comme vous pouvez le voir. L’important ici est " a 2..n,: tâches ". Cette validation fonctionne normalement, étant donné que les attributs de tâches imbriqués dans le hachage params produiront des tâches valides . S'ils génèrent une tâche non valide , toutefois, la tâche ne sera pas créée et vous obtiendrez un projet comportant moins de 2 tâches, et donc un non valide objet du projet.

Si j'ai bien compris, cela est dû au fait qu'il ne peut pas déterminer si les attributs de tâche sont valides ou non tant qu'il n'a pas tenté de sauvegarder les tâches. Depuis, autant que je sache , les tâches ne peuvent pas être enregistrées avant le projet, le projet ignore si les tâches seront valides ou non. Ai-je raison de supposer cela?

Quoi qu'il en soit, j'espérais une réponse rapide, mais cela semble beaucoup moins trivial que je ne l'avais espéré. Si vous avez des suggestions, nous vous en serions très reconnaissants.

Était-ce utile?

La solution

En fait, j'ai trouvé une solution intéressante en utilisant des transactions dans DataMapper. Fondamentalement, cette transaction essaie de sauvegarder l’objet parent ainsi que tous les objets enfants. Dès que la sauvegarde échoue, la transaction s'arrête et rien n'est créé. Si tout se passe bien, les objets seront sauvegardés avec succès.

class Project
  def make
    transaction do |trans|
      trans.rollback unless save
      tasks.each do |task|
        unless task.save
          trans.rollback
          break
        end
      end
    end
  end
end

Cela garantit que tout est valide avant que quelque chose soit sauvegardé. Je devais juste changer mes méthodes #save et #update pour #make dans le code de mon contrôleur.

Autres conseils

SET CONSTRAINTS DEFERRED peut être utile si votre moteur de base de données le prend en charge.

Sinon, écrivez peut-être une procédure stockée pour effectuer les insertions, puis dites que c’est la responsabilité de la procédure stockée de s’assurer que seules les données correctes et validées sont insérées.

Il existe une méthode de modèle valide? qui exécute les validations sur un objet de modèle avant son enregistrement. Ainsi, le moyen simple de valider les associations serait d'utiliser validates_with_block 'ou' validates_with_method pour vérifier les validations des associations.

Cela ressemblerait à quelque chose comme ça

validates_with_block do
  if @tasks.all?{|t|t.valid?}
    true
  else
    [false, "you have an invalid task"]
  end
end

Vous pouvez également consulter dm-association-validator ou attributs dm-accepte-imbriqués

Modifier: pour un extra fou. exécutez des validations sur les tâches, puis vérifiez si les seules erreurs sont celles liées à l'association.

validates_with_block do
  if @tasks.all?{|t|t.valid?;!t.errors.any?{|e|e[0]==:project}}
    true
  else
    [false, "you have an invalid task"]
  end
end
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top