Problems with Mongoid::Errors::Callback:
- Mongoid::Errors::Callback is not correctly worded. It says "...resulted in a false return from a callback", but as of Rails 5, returning false from an ActiveModel callback doesn't not have any effect: https://www.bigbinary.com/blog/rails-5-does-not-halt-callback-chain-when-false-is-returned
- This wording should be changed to "...threw an :abort"
- In addition, the error does not tell us which callback actually failed.
- Lastly, in some cases, I think it is actually possible that this error is raised even if no callback was aborted, but if the save failed for any other reason, which is confusing. I see this happening in my app after upgrading to Mongoid 9, but I am still trying to pin down the actual problem.
To fix/clarify things, I'd like would propose the following enhancement:
- Make a new error class "Mongoid::Errors::CallbackAborted". This should be raised during the actual abort, and make it clear in the error exactly which callback was aborted.
- If no callback aborted, instead, raise a new generic error class "Mongoid::Errors::PersistenceFailed"
- To preserve the legacy error, make:
- Mongoid::Errors::Callback = Mongoid::Errors::PersistenceFailed
- Mongoid::Errors::CallbackAborted < Mongoid::Errors::PersistenceFailed (CallbackAborted is a subclass)
—
Demonstration that returning false in a callback has no effect in MongoDB:
class Person include Mongoid::Document before_save :return_false def return_false throw(:abort) end end Person.new.save! #=> true, it works!
Instead, this error is raised if you throw(:abort)
class Person include Mongoid::Document before_save :throw_abort def throw_abort throw(:abort) end end Person.new.save! #=> raises error blelow
Mongoid::Errors::Callback: message: Calling save! on Person resulted in a false return from a callback. summary: If a before callback returns false when using Document.create!, Document#save!, or Document#update_attributes! this error will get raised since the document did not actually get saved. resolution: Double check all before callbacks to make sure they are not unintentionally returning false.