Categories
Home
About Collection Agency
Collection Agency Classification
Nationwide Collection Agency
Site Map
 
 
   
association collection find vs ordinary array find

Question:
association collection find vs ordinary array find 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:
1) Maybe the trip to the db is more expensive than filtering in memory. Is it assumed that this will never be the case?
2) 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.


Answer:
Q: 1) Maybe the trip to the db is more expensive than filtering in memory. Is it assumed that this will never be the case?
A: Most likely, this *is* the case. The database server is specialized to be able to do these kinds of operations, so the database server is probably going to be able to do the restriction faster (and in compiled code, no less), than Ruby. Also, you have the overhead of sending all of the data -- including that which you're just going to throw away--over the wire to the middleware. Taking just those two into account, I think it's a safe bet that using the database server to handle the filtering is going to be a win. Q: But there's no pretty way to do that filtering in memory.
A: I haven't looked at the ActiveRecord source, but I'd think it's likely that Array.find has been aliased rather than just left hanging. If you're motivated to do so, you might be able to work something to your liking using the alias.



Submit your comment or answer


 

Home About Collection Agency Collection Agency Classification Nationwide Collection Agency Site Map


Privacy Policy