2012-01-30 4 views
47

로그에 ROLLBACK이 표시되지만 예외는 기록되지 않습니다. 롤백의 원인을 찾아내는 방법이 있습니까?ActiveRecord 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 
+1

ROLLBACK 주변의 로그는 무엇입니까? –

+1

오류가 없습니다. 또한 다음 번에는 트랜잭션을 사용하지 않는 것이 이상한 일입니다. 그 두 조각이 무관하지 않다면 말이지. – m33lky

+0

트랜잭션 내부에서 SELECT가 원인이되는 것은 무엇입니까? –

답변

46

한 가지 방법은 수동으로 로그에 정보를 기록하는 것입니다. 컨트롤러에서 다음과 같이 시도하십시오.

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

오류가 발생한 모든 유효성 검사의 내용을 출력해야합니다.

1) 활성 레코드를 엽니 다) 모든 관련 확인, 저장 방법

2

을에 활성 기록에 관찰자를 사용하려면 내가 함께 올라와있다

7

3 방법론 (1 실패)이며, ROLLBACK이 트리거 된 디버거 문을 넣은 다음 caller을 실행하여 오류를 트리거 한 코드를 찾아냅니다.

3) 실패 : 활성 레코드 메서드를 무시하고 예외가 발생하면 일시 중지합니다. 저장 메소드가 트랜잭션에 랩핑되어 있기 때문에이 메소드가 예외를 포착하지 않는다는 것을 기억합니다.

참고 : 모드가 Rails.env.production?이 아닌 경우에만 활성화하십시오. Ruby 1.9.3을 사용하여 Rails 3.2.13에서 테스트되었습니다.

1) 관찰자 :

 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) 

레일 서버 또는 콘솔을 역 추적을 얻을 수 caller에 중단 점 유형 안타 activerecord` 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`번들 쇼 .

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 
19

1) 해제 before_create에 넣고 , before_save는, 그 방법은 반환 확인,을 before_update하고 롤백이 그 방법 중 하나가 발생한 경우 일

2를) 저장 위치를 ​​확인 롤백을 계획하지 않을 때 참. 예를 들어

당신은이 예제 방법 항상 거짓를 반환하고, 따라서 거래를 롤백 set_defaults_before_create에서는이 방법

def set_defaults_before_create 
    self.my_boolean_field ||= false 
end 

을 아마 것, 전무을 피하기 위해 부울 필드에 대한 기본 값을 설정합니다. 그래서 리팩토링하는 사람이 돌아 오면

def set_defaults_before_create 
    self.my_boolean_field ||= false 
    true 
end 
+4

그것은 미묘한 문제였습니다. 지적 해 주셔서 고맙습니다! – vemv

+1

당신은 매우 환영합니다. @vemv –

+2

나는이 문제를 디버깅하려고 하루를 보냈습니다. 고마워요 :)) – Subtletree

62

BANG '!'런타임 오류가 발생하여 어디서 발생하는지 알 수 있습니다.

+10

답변으로 표시해야합니다. – wuliwong

+0

잘 모르겠습니다. 내 경우 엔'destroy '에 ROLLBACK을 사용하고 있는데,이 경우 선택한 응답이 도움이 될 것 같지만이 것은 적용되지 않습니다. –

+0

나는 이것을 여러 번 upvote 할 수 있으면 좋겠다. 그것은 나를 여러 번 구했습니다. – BigRon

관련 문제