如何findActiveRecord ROLLBACK的原因

在日志中,我看到一个ROLLBACK ,但没有例外logging。 有没有办法找出是什么导致了ROLLBACK?

这里是日志的摘录:

  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 

用BANG保存logging'!' 所以它会造成运行时错误,你会知道它发生了什么

一种方法是手动将信息写入日志。 尝试从你的控制器这样的事情:

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

这应该输出所有失败的validation内容。

1)禁用before_create,before_sup,before_update并检查它保存的date

2)如果回滚是由这些方法之一引起的,请检查在不打算回滚的情况下这些方法返回true。

例如,如果你为布尔型字段设置默认值以避免零,你可能会这样做

 def set_defaults_before_create self.my_boolean_field ||= false end 

在这个例子中, set_defaults_before_create方法总是返回false ,从而回滚事务。 所以重构它返回true

 def set_defaults_before_create self.my_boolean_field ||= false true end 

3个方法(1个失败)我已经拿出来了

1)在所有相关的保存,validation方法上使用活动logging中的观察者

2)打开活动logging,并在触发ROLLBACKs的地方放一个debugging器语句,然后运行caller来查找触发错误的代码。

3)失败:覆盖活动logging方法并暂停exception。 如果我记得这个方法没有捕获任何exception,因为保存方法被封装在一个事务中。

注意:只有在模式不是Rails.env.production时才能使用。 testingRails 3.2.13,使用ruby1.9.3。

1)观察者: 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`bundle show activerecord`

  Put a debugger statement when where the rollback is executed. /Users/<user>/.rvm/gems/ruby-1.9.3-<env>/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) 

当Rails服务器或控制台在caller击中断点types以获得回溯时。

3)在开发模式下重写AR。 TODO:只有覆盖!Rails.env.production? 把它放在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