Ответ 1
сохранить запись с помощью BANG '!' поэтому он сделает ошибку времени выполнения, и вы узнаете, где это происходит.
В журналах я вижу 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
сохранить запись с помощью BANG '!' поэтому он сделает ошибку времени выполнения, и вы узнаете, где это происходит.
Один из способов - вручную записать информацию в журнал. Попробуйте что-то вроде этого от вашего контроллера:
Rails.logger.info(@your_object.errors.inspect)
Это должно выводить содержимое всех недействительных проверок.
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
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