web-dev-qa-db-fra.com

Quand dois-je utiliser save !, create! et update_attributes! dans Rails?

J'essaie de savoir quand utiliser le bang! versions pour sauvegarder 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 que vous devez toujours les utiliser en dehors d'un contrôleur. Je suppose que je suis paranoïaque d'avoir plusieurs choses enregistrées, puis quelque chose échoue, puis il y a des données incomplètes dans la base de données. Le projet Rails sur lequel je travaille est terminé à plus de 50% et ne contient actuellement aucune frange. J'ai des méthodes personnalisées que j'appelle dans des modèles qui mettent à jour ou créent plusieurs enregistrements et s'inquiéter s'ils doivent être dans une sorte de transaction.

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

60
CalebHC

En règle générale, vous souhaitez utiliser les versions non-bang dans vos contrôleurs. Cela permet une logique comme celle-ci:

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 me retrouve à utiliser les versions bang beaucoup dans les tests lorsque je veux m'assurer que je sais si quelque chose ne valide pas et n'est pas enregistré. J'ai définitivement perdu du temps à déboguer des tests qui échouaient en raison de modifications de validation de modèle, 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

Pour ne pas avoir de données non valides dans la base de données, vous devez les gérer avec des validations ActiveRecord (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. Vérifier la ActiveRecord::Migration documents pour savoir comment configurer des index uniques et d'autres contraintes de base de données dans vos migrations.

De plus, d'après mon expérience, vous voulez éviter d'utiliser une méthode d'enregistrement ou de création personnalisée dans la mesure du possible. Si vous réimplémentez les fonctionnalités incluses dans ActiveRecord, vous finissez par payer un prix plus tard. http://matthewpaulmoore.com/post/5190436725/Ruby-on-Rails-code-quality-checklist a plus à dire à ce sujet.

51
samg

La principale différence est la façon dont les sauvegardes échouées sont gérées. Lors de la mise à jour d'une classe ActiveRecord, le ! la version lèvera une exception si l'enregistrement n'est pas valide.

Je recommande de lire les documents ici - http://api.rubyonrails.org/classes/ActiveRecord/Base.html

L'utilisation de transactions peut également être intéressante - http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

76
Andy Gaskell

Quoi! (bang) signifie pour update_attributes et save est:

"Soulever une exception en cas d'échec" plutôt que "Retourner faux en cas d'échec"

https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update-21https://api.rubyonrails.org/classes/ActiveRecord/ Persistence.html # method-i-save

Quoi! (bang) signifie pour create est:

"Lève une exception en cas d'échec" plutôt que "Renvoie l'objet résultant en cas d'échec" https://api.rubyonrails.org/classes/ActiveRecord/Persistence/ClassMethods.html#method-i-create-21 =

3
Tim Heilman