Once you find that the insult callback will be as follows:
before_create :activate_license def activate_license self.active_license = true self.licensed_date = Time.now end
things are becoming clearer. activate_licence is before the callback. Before callbacks can stop the whole chain of callbacks by returning false (or throwing an exception).
If we carefully consider the debugging output that you provided by adding a few puts lines to the Rails callbacks code, we can really find a comparison of this callback result with a false one ( here I deleted some irrelevant parts of the code):
result = activate_license halted = (result == false) if halted halted_callback_hook(":activate_license") end
Since the support for stopping before callbacks by returning false (that is, the Rails code shown above) has not practically changed from Rails 3.2 to Rails 4.0.1 , the problem should lie in the comparison itself.
The callback returns a DateTime object (this is the last assignment in the method, which is also returned). Indeed, the DateTime comparison has changed significantly between the two versions of Rails (also note that the == operator is usually evaluated using the <=> operator ):
in Rails 3.2 it was this :
def <=>(other) if other.kind_of?(Infinity) super elsif other.respond_to? :to_datetime super other.to_datetime else nil end end
pay attention in particular to respond_to? check if the other object is also a date or time object, otherwise nil returned.
whereas in Rails 4.0.1 this one has changed to below:
def <=>(other) super other.to_datetime end
→ all health checks failed !
Now everything is clear: the result of the callback ( DateTime object) is compared using the operator <=> with false and under Rails 4.0, the comparison tries to convert the false object to DateTime without any sanity checks, which, of course, fails and throws an exception.
To fix this problem, just make sure your callback returns what Rails can compare to false without any problems , for example. true , since your callback should never stop the chain:
def activate_license self.active_license = true self.licensed_date = Time.now true end
Now everything should work as expected.
Borama
source share