2010-01-25 5 views
2

J'ai 2 modèlesbefore_filter ou de sauvetage pour créer un nouveau record

class Room < ActiveRecord::Base 
    has_many :people 
    accepts_nested_attributes_for :people, :reject_if => lambda { |a| a[:person_id].blank? }, :allow_destroy => true 
end 

class Person < ActiveRecord::Base 
    belongs_to :room 
end 

Sous forme «/chambres/nouvelle » J'ai une balise select contenant toutes personne + une balise option « autre » qui permettent à la utilisateur pour ajouter dynamiquement une personne à la balise de sélection (Nouveau nom). Donc, quand je soumets mon formulaire, je peux avoir une personne avec id = -1 qui n'existe pas dans la base de données, et bien sûr, je veux créer une nouvelle personne avec le nouveau nom. Je me demande quelle est la meilleure façon d'y parvenir?

avec un « before_filter » ou un « sauvetage ActiveRecord :: RecordNotFound » ou ...

Merci pour votre aide

Répondre

2

En règle générale, je ne suggère d'utiliser la gestion des exceptions comme le contrôle de logique fonctionnelle. Donc, je préconise de vérifier pour un ID de -1, et de créer la personne dans ce cas, plutôt que de le faire après le fait dans un bloc de sauvetage.

Si vous cherchez une raison, 2 je pense à la performance et la clarté.

Les exceptions sont coûteuses et vous ne voulez pas encourir le coût de traitement si elles peuvent être évitées. De plus, les exceptions sont destinées à indiquer une condition d'erreur, et non un chemin prévu dans votre logique. En les utilisant de cette façon, vous êtes en train de brouiller les eaux, et donner l'impression que cela n'est pas fait pour marcher à sa guise. En ayant le chèque pour une personne non-existante dans le filtre avant, il est plus clair que cela est supposé arriver parfois, et il est clair que cela se produit avant le reste de la sauvegarde. De plus, si vous avez cette logique dans la gestion de l'exception, vous devez réessayer l'opération qui a échoué, ce qui rend votre logique de sauvegarde beaucoup plus complexe en faisant une boucle ou en étant récursive ou en dupliquant la sauvegarde défaillante. Cela rendra également votre code moins clair pour le codeur suivant qui doit travailler dessus.

+0

Je suis d'accord avec vous, les exceptions doivent être utiliser que pour détecter les erreurs et non pour la logique fonctionnelle, merci pour votre réponse – denisjacquemin

2

Vous n'avez besoin d'aucun code spécial. ActiveRecord inclut déjà une logique pour gérer ce cas.

Lire la rdoc au http://github.com/rails/rails/blob/2-3-stable/activerecord/lib/active_record/nested_attributes.rb#L328 ou http://github.com/rails/rails/blob/master/activerecord/lib/active_record/nested_attributes.rb#L332 pour les détails. Essentiellement, si le Hash est passé avec une clé: id, les attributs de cet enregistrement sont mis à jour. Si l'enregistrement n'a pas de: id, un nouvel enregistrement est créé. S'il a une clé: id, et une clé: _destroy avec une valeur true, l'enregistrement sera supprimé.

Voici la documentation de la branche 2-3 stable:

# Assigns the given attributes to the collection association. 
# 
# Hashes with an <tt>:id</tt> value matching an existing associated record 
# will update that record. Hashes without an <tt>:id</tt> value will build 
# a new record for the association. Hashes with a matching <tt>:id</tt> 
# value and a <tt>:_destroy</tt> key set to a truthy value will mark the 
# matched record for destruction. 
# 
# For example: 
# 
# assign_nested_attributes_for_collection_association(:people, { 
# '1' => { :id => '1', :name => 'Peter' }, 
# '2' => { :name => 'John' }, 
# '3' => { :id => '2', :_destroy => true } 
# }) 
# 
# Will update the name of the Person with ID 1, build a new associated 
# person with the name `John', and mark the associatied Person with ID 2 
# for destruction. 
# 
# Also accepts an Array of attribute hashes: 
# 
# assign_nested_attributes_for_collection_association(:people, [ 
# { :id => '1', :name => 'Peter' }, 
# { :name => 'John' }, 
# { :id => '2', :_destroy => true } 
# ]) 
Questions connexes