如何找到ActiveRecord ROLLBACK的原因

时间:2012-01-30 06:08:35

标签: ruby-on-rails activerecord

在日志中我看到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

4 个答案:

答案 0 :(得分:87)

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

答案 1 :(得分:47)

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

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

那应该输出失败的所有验证的内容。

答案 2 :(得分:21)

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

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

例如,如果你为boolean字段设置默认值以避免nil,你可能会这样做

def set_defaults_before_create
  self.my_boolean_field ||= false
end

在此示例方法中, set_defaults_before_create 始终返回 false ,从而回滚您的交易。所以重构它以返回真实的

def set_defaults_before_create
  self.my_boolean_field ||= false
  true
end

答案 3 :(得分:7)

我提出的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

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)

当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