comment trouver la cause de ActiveRecord ROLLBACK

Dans les journaux, je vois un ROLLBACK , mais aucune exception n’est consignée. Est-il possible de savoir ce qui a causé le ROLLBACK?

Voici l’extrait du journal:

  Phone Load (0.4ms) SELECT "phones".* FROM "phones" WHERE "phones"."id" = $1 LIMIT 1 [["id", 980190963]] (0.2ms) BEGIN User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."phone_id" = 980190963 LIMIT 1 (0.2ms) ROLLBACK Phone Load (0.4ms) SELECT "phones".* FROM "phones" WHERE "phones"."id" = $1 LIMIT 1 [["id", 980190963]] User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."phone_id" = 980190963 LIMIT 1 

enregistrer l’enregistrement avec BANG ‘!’ il va donc faire une erreur d’exécution et vous savez où cela se passe

L’une des méthodes consiste à écrire manuellement des informations dans le journal. Essayez quelque chose comme ça de votre contrôleur:

 Rails.logger.info(@your_object.errors.inspect) 

Cela devrait générer le contenu de toutes les validations qui ont échoué.

1) Désactivez before_create, before_save, before_update et vérifiez où il enregistre le jour

2) Si la restauration a été provoquée par l’une de ces méthodes, vérifiez que ces méthodes renvoient la valeur true lorsque vous ne prévoyez pas de restauration.

Par exemple, si vous définissez une valeur par défaut pour le champ booléen afin d’éviter toute valeur nulle, vous le feriez probablement de cette façon.

 def set_defaults_before_create self.my_boolean_field ||= false end 

Dans cet exemple, la méthode set_defaults_before_create renvoie toujours false et annule ainsi votre transaction. Donc refactor it pour retourner true

 def set_defaults_before_create self.my_boolean_field ||= false true end 

Les 3 méthodologies (1 en échec) que j’ai inventées sont

1) utiliser un observateur sur un enregistrement actif sur toutes les sauvegardes pertinentes, valider les méthodes

2) d’ouvrir l’enregistrement actif et de placer une instruction de débogage dans laquelle les ROLLBACK sont déclenchés, puis d’exécuter l’ caller pour identifier le code qui a déclenché l’erreur.

3) Failed: remplace les méthodes d’enregistrement actives et fait une pause sur exception. Si je me souviens de cette méthode, aucune exception n’est détectée car les méthodes de sauvegarde sont regroupées dans une transaction.

Remarques: Activez uniquement lorsque le mode n’est pas Rails.env.production?. Testé sur Rails 3.2.13, avec ruby ​​1.9.3.

1) Observateur: http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#observers

 class ActiveRecordObserver < ActiveRecord::Observer observe "ActiveRecord::Base" def after_validation(model) debugger if model.errors.messages.any? Rails.logger.error "after validation" end def before_update(model) debugger if !model.valid? Rails.logger.error "before update" end def after_update(model) debugger if !model.valid? Rails.logger.error "after update" end def before_save(model) debugger if model.errors.messages.any? Rails.logger.error "#{model}" Rails.logger.error "before save" end def after_save(model) debugger if model.errors.messages.any? Rails.logger.error "after save" end end 

2) https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb#L231 cd `show bundle activerecord`

  Put a debugger statement when where the rollback is executed. /Users//.rvm/gems/ruby-1.9.3-/gems/activerecord-3.2.14/lib/active_record/connection_adapters/abstract/database_statements.rb 196 transaction_open = false 197 decrement_open_transactions 198 if open_transactions == 0 199 rollback_db_transaction 200 debugger => 201 rollback_transaction_records(true) 202 else 203 rollback_to_savepoint 204 debugger 205 rollback_transaction_records(false) 

Lorsque le serveur ou la console de rails frappe le type de point d'arrêt dans l' caller pour obtenir la trace arrière.

3) Remplacez AR en mode de développement. TODO: ne remplace que si! Rails.env.production? Mettez ceci dans app/config/initializers/active_record_or_any_file_name.rb

 ActiveRecord::Base.class_eval do alias_method :old_save, :save alias_method :old_save!, :save! def save(*args) begin puts "#{self} save" Rails.logger.info "#{self} save" old_save(*args) rescue Exception => e debugger puts e end end def save!(*args) begin Rails.logger.info "#{self} save!" puts "#{self} save!" old_save!(*args) rescue Exception => e debugger puts e end end end