I am upgrading a project from Rails 2.3.2 to 2.3.15. It appears that exists? may now be considered a finder, which means functions such as after_find are now callbacks from exists?.
In 2.3.2 exists? did not trigger a callback to after_find. I am having trouble finding a readable changelog other than commits on github which explicitly names this change in policy.
Can someone confirm that exists? did not call after_find (should it be present) in 2.3.2 and it does in 2.3.15?
If this is the case, is there a clean Rails way to segregate the after_find call? I need some code executed after a true find, not after an exists?.
As a temporary work-around, I am experimenting with making this the first line in my model’s after_find:
return unless self.has_attribute?(:some_attrib_your_model_uses_in_after_find)
There are three ways to do this that I’ve found, none of them satisfactory but at least two of them will work reliably, even if they’re surprising in design and can create some very subtle bugs down the road.
A) Return if an Attribute You’ll Use is Missing
B) Grep the Entire Callstack
(and pray exists? is in there because you think it is)
I’m ashamed to post this as an option, but it’s good to see what you can do with the array of strings available to
caller. Let’s just hopecallerdoesn’t change the formatting.Using 2.3.15 from the console, the callstack to my model’s after_find() is:
C) Make the Model Eager-Load
Some people might want to do this, an the 2.3.15 ActiveRecord README hints at it:
I don’t want to put any more burden on the DB than I must. The point of calling
exists?in many cases is to do a simple single-column lookup. Performing eager loading of a whole model and potentially its associations just to do anexists?call is going to cause a performance hit.