Подтвердить что ты не робот

Как найти причину ActiveRecord ROLLBACK

В журналах я вижу 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
4b9b3361

Ответ 1

сохранить запись с помощью BANG '!' поэтому он сделает ошибку времени выполнения, и вы узнаете, где это происходит.

Ответ 2

Один из способов - вручную записать информацию в журнал. Попробуйте что-то вроде этого от вашего контроллера:

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

Это должно выводить содержимое всех недействительных проверок.

Ответ 3

1) Отключите before_create, before_save, before_update и проверьте, где он сохраняет день

2) Если откат вызван одним из этих методов, убедитесь, что эти методы возвращают true, если вы не планируете откатываться.

Например, если вы установите значение по умолчанию для логического поля, чтобы избежать nil, вы, вероятно, сделаете это так.

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

Ответ 4

3 метода (1 не удалось), с которыми я столкнулся, заключаются в

1) используйте наблюдателя в активной записи во всех соответствующих файлах сохранения, проверки достоверности

2), чтобы открыть активную запись и поставить инструкцию отладчика, где запускаются ROLLBACK, а затем запустить caller, чтобы определить код, вызвавший ошибку.

3) Не удалось: переопределить методы активной записи и приостановить исключение. Если я помню, этот метод не вызывает никаких исключений, потому что методы сохранения завернуты в транзакцию.

Примечания: Включить только, если режим не Rails.env.production?. Протестировано на Rails 3.2.13, используя ruby ​​1.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, чтобы получить обратную трассировку.

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