2009-11-19 3 views
51

J'essaie de comprendre quand utiliser le bang! versions pour enregistrer et mettre à jour les enregistrements? J'ai lu et entendu que vous n'en avez pas besoin si vous enregistrez simplement un enregistrement ou mettez à jour un seul attribut, si vous êtes sûr que rien ne devrait aller mal, ou si vous les utilisez toujours en dehors d'un contrôleur. Je suppose que je suis paranoïaque à propos de la sauvegarde de plusieurs choses, puis que quelque chose échoue, il y a des données incomplètes dans la base de données. Le projet Rails actuel sur lequel je travaille est terminé à plus de 50% et ne contient actuellement aucune bang. J'ai des méthodes personnalisées que j'appelle dans les modèles qui mettent à jour ou créent plusieurs enregistrements et m'inquiètent s'ils devraient être dans une sorte de transaction.Quand est-ce que j'utilise save !, create! et update_attributes! dans Rails?

Désolé si cela semble dispersé mais j'essaie juste de comprendre comment utiliser les capacités d'enregistrement dans ActiveRecord correctement et de rendre ma vie plus facile et un peu plus sans stress à la fin. Merci pour votre temps.

Répondre

49

En général, vous souhaitez utiliser les versions non-bang dans vos contrôleurs. Cela permet à la logique comme ceci:

def update 
    @model = Model.find params[:id] 
    if @model.update_attributes params[:model] #returns true of false 
    # handle success 
    else 
    # handle failure 
    end 
end 

Je trouve moi-même en utilisant les versions bang beaucoup dans les tests quand je veux assurer que je sais si quelque chose ne valide pas, et ne sont pas enregistrées. J'ai certainement perdu du temps à déboguer des tests qui échouaient à cause des changements de modèles, ce qui serait évident si j'utilisais les versions bang.

par exemple.

it "should do something" do 
    m = Model.create! :foo => 'bar' # will raise an error on validation failure    
    m.should do_something 
end 

En termes de ne pas avoir des données non valides dans la base de données, vous devriez être avec la manipulation de ce ActiveRecord de validation (par exemple validates_presence_of :user_id), ou définir votre propre méthode validate dans le modèle. (http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html) Cela devrait empêcher les sauvegardes de se produire si vos données ne sont pas valides. Si vous êtes vraiment paranoïaque, vous pouvez ajouter des contraintes à votre base de données. Consultez les documents ActiveRecord::Migration pour savoir comment configurer des index uniques et d'autres contraintes de base de données dans vos migrations.

Dans mon expérience, vous voulez éviter d'utiliser une sauvegarde personnalisée ou créer une méthode autant que possible. Si vous ré-implémentez les fonctionnalités incluses dans ActiveRecord, vous finirez par payer un prix plus tard. http://matthewpaulmoore.com/post/5190436725/ruby-on-rails-code-quality-checklist a plus à dire à ce sujet.

67

La principale différence réside dans la manière dont les sauvegardes échouées sont gérées. Lors de la mise à jour d'une classe ActiveRecord, la version ! lèvera une exception si l'enregistrement est invalide.

Je recommande la lecture de la documentation ici - http://api.rubyonrails.org/classes/ActiveRecord/Base.html

transactions à l'aide peut aussi être quelque chose dignes d'intérêt - http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

+16

Idéal pour pointer la différence clé entre les deux, contrairement à la réponse sélectionnée. – ifightcrime

+0

Merci de souligner l'utilisation des transactions, ils semblent souvent négligés. – ki4jnq

+2

+1. Il peut également être intéressant de noter que les méthodes non-bang échouent silencieusement dans les transactions, donc utilisez toujours 'save!', 'Update_attributes! ', Etc. lorsque votre code est encapsulé dans une transaction. –

Questions connexes