如何找到ActiveRecord ROLLBACK的原因

m33*_*lky 59 activerecord ruby-on-rails

在我看到的日志中ROLLBACK,但没有记录任何异常.有没有办法找出导致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
Run Code Online (Sandbox Code Playgroud)

Nit*_*ain 97

用BANG'!'保存记录 所以它会产生运行时错误,你会知道它发生在哪里

  • 这应该标记为答案. (14认同)
  • 我希望我能多次对此表示赞同。它多次救了我。 (2认同)
  • 谢谢老哥,我很快就发现了问题!(<-你明白了吗?哈哈) (2认同)

Dan*_*nne 49

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

Rails.logger.info(@your_object.errors.inspect) 
Run Code Online (Sandbox Code Playgroud)

这应该输出失败的所有验证的内容.


Ser*_*kyy 23

1)禁用before_create,before_save,before_update并检查它保存当天的位置

2)如果回滚是由其中一种方法引起的,请在不打算回滚时检查这些方法是否返回true.

例如,如果为boolean field设置默认值以避免nil,那么您可能会这样做

def set_defaults_before_create
  self.my_boolean_field ||= false
end
Run Code Online (Sandbox Code Playgroud)

在此示例方法中,set_defaults_before_create始终返回false,从而回滚您的事务.因此重构它以返回true

def set_defaults_before_create
  self.my_boolean_field ||= false
  true
end
Run Code Online (Sandbox Code Playgroud)

  • 这是一个微妙的问题,谢谢你的指出! (4认同)
  • 第二点解决我的问题.方法需要返回true,我认为即使我们将其用于其他目的,它也用于验证目的. (4认同)
  • 我花了大约一天试图调试这个问题.非常感谢 : ) (2认同)

dav*_*gsu 8

我想出的3种方法(1种失败)是

1)在所有相关的保存,验证方法上使用活动记录上的观察者

2)打开活动记录并将调试器语句放在ROLLBACK被触发的位置,然后运行caller以查明触发错误的代码.

3)失败:覆盖活动记录方法并暂停异常.如果我记得这个方法没有捕获任何异常,因为save方法被包装在一个事务中.

注意:仅在模式不是Rails.env.production时启用?使用ruby 1.9.3在Rails 3.2.13上测试.

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
Run Code Online (Sandbox Code Playgroud)

2) https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb#L231 cd`s束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)
Run Code Online (Sandbox Code Playgroud)

当rails服务器或控制台命中断点时,键入caller以获得回溯.

3)在开发模式下覆盖AR​​.TODO:只覆盖if!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
Run Code Online (Sandbox Code Playgroud)