Ruby-on-rails 如何找到ActiveRecord ROLLBACK的原因
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9060014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to find the cause of ActiveRecord ROLLBACK
提问by m33lky
In the logs I'm seeing a ROLLBACK, but no exception is logged. Is there a way to find out what caused the ROLLBACK?
在日志中,我看到了ROLLBACK,但没有记录异常。有没有办法找出导致回滚的原因?
Here's the excerpt of the log:
这是日志的摘录:
Phone Load (0.4ms) SELECT "phones".* FROM "phones" WHERE "phones"."id" = 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" = LIMIT 1 [["id", 980190963]]
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."phone_id" = 980190963 LIMIT 1
回答by Nitin Jain
save record with BANG '!' so it will make a run time error and you get know where does it happens
用 BANG '!' 保存记录 所以它会产生一个运行时错误,你会知道它发生在哪里
回答by DanneManne
One way is to manually write information to the log. Try something like this from your controller:
一种方法是手动将信息写入日志。从您的控制器尝试这样的事情:
Rails.logger.info(@your_object.errors.inspect)
That should output the content of all validations that failed.
那应该输出所有失败的验证的内容。
回答by Serge Seletskyy
1) Disable before_create, before_save, before_updateand check where it saves the day
1) 禁用before_create、before_save、before_update并检查它保存一天的位置
2) If rollback was caused by one of those methods, check that those methods return true when you don't plan to rollback.
2) 如果回滚是由这些方法之一引起的,当您不打算回滚时,请检查这些方法是否返回 true。
For example if you set default value for boolean field to avoid nil, you would probably do it this way
例如,如果您为布尔字段设置默认值以避免 nil,您可能会这样做
def set_defaults_before_create
self.my_boolean_field ||= false
end
In this example method set_defaults_before_createalways returns falseand thus rollbacks your transaction. So refactor it to return true
在这个例子中,set_defaults_before_create方法总是返回false,从而回滚你的事务。所以重构它以返回true
def set_defaults_before_create
self.my_boolean_field ||= false
true
end
回答by davidtingsu
The 3 methodologies (1 failed) I have come up with are to
我提出的 3 种方法(1 失败)是
1) use an observer on active record on all the relevant save, validate methods
1) 在所有相关的保存、验证方法的活动记录上使用观察者
2) to open up active record and put a debugger statement where ROLLBACKs are triggered and then run callerto pinpoint the code that triggered the error.
2) 打开活动记录并在触发 ROLLBACK 的地方放置一个调试器语句,然后运行caller以查明触发错误的代码。
3) Failed :override the active record methods and pause on exception. If I remember this method does not catch any exception because the save methods are wrapped in a transaction.
3)失败:覆盖活动记录方法并在异常时暂停。如果我记得这个方法没有捕获任何异常,因为保存方法被包装在一个事务中。
Notes: Only enable when the mode is not Rails.env.production?. Tested on Rails 3.2.13, using ruby 1.9.3.
注意:仅在模式不是 Rails.env.production? 时启用。在 Rails 3.2.13 上测试,使用 ruby 1.9.3。
1) Observer: http://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html#observers
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#L231cd `bundle show activerecord`
2) https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb#L231cd `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)
When the rails server or console hits the breakpoint type in callerto get the backtrace.
当 Rails 服务器或控制台命中断点时,请键入 incaller以获取回溯。
3) Override AR in development mode. TODO: only override if !Rails.env.production?
Put this in app/config/initializers/active_record_or_any_file_name.rb
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

