So on an ordinary Array, #find filters through the elements (in memory,
naturally), for what you’re looking for.
But ActiveRecord to-many associations redefine #find to behave like the
ordinary ActiveRecord find, going to the db, but limited to the objects
in that association (ie, probably the same objects that were in memory
in the array—unless the db has changed since cache!).
There are a couple reasons why I might prefer to filter in memory
instead:
-
Maybe the trip to the db is more expensive than filtering in memory.
Is it assumed that this will never be the case? -
If I find an object through the existing AR find (by going to the
db), and I make changes to it, and save!—my cached version in
ar_obj.some_has_many is still unchanged, even though it was changed in
the db, becuase it’s a different object in memory. To fix this, I’ve
got to call ar_obj.some_has_many(true) to reload the cache from the db.
Now I’ve taken TWO extra trips to the db, compared to the other option:
just filtering the cached ar_obj.some_has_many array in memory, finding
the already loaded destination object that meets my conditions in there,
modifying it, and calling save!. I skipped the initial select to the db
for the ‘find’, and I skipped the reloading of the cached has_many in
case I want the ar_obj to have the updated value in it’s cached array.
But there’s no pretty way to do that filtering in memory. I guess I can
use ‘collect’ instead, and then call compact! on the subsequent array to
get rid of all the nils that represented things I wanted to filter out.
Hmm, I guess that is a pretty decent way after all. I just thought of
that.
But are other Rails developers running into this sort of thing, and how
do you deal with it? It surprised me to see the normal array #find
completely unavailable, since it seemed like it would still be useful in
an AR has_many, for the reasons outlined above.
Jonathan