views:

115

answers:

2

I have a simple find statement as such:

m = MyModel.find(1, :include => :my_children)

With m.mychildren being an Array; is there anyway to find a particular record from within the array without having to iterate over the entire thing. If I do mychildren.find(1), a new DB query is issues, which doesn't make sense, since they are all loaded already

A: 

I'm not quite sure what your asking, but have you tried select:

m.mychildren.select{ |child| child == <<some_statement>> }

This won't hit the database assuming you've used the :include option as you stated in your question.

Alternatively, if you know the number of the child you want, you should be able to just use

m.mychildren[1]
Topher Fangio
I know the id of the child, not the index in the array. I am aware of the default ruby Array functions. I was just wondering if there was some rails monkeypatch which added a bit more support for looking up children.
gmoniey
A: 

It looks like there's a little Rails magic going on here. Where Enumerable#find is being overridden by ActiveRecord::Base#find on methods created for associations.

On the upside Enumerable#find is aliased to Enumerable#detect. Unfortunately Enumerable#find/Enumerable#detect have significantly different syntax from ActiveRecord::Base#find.

So you can't just do mychildren.find(1), instead you've got to do mychildren.detect{|c| c.id == 1} if you want to avoid hitting the database again. You may also want to consider extending Array for a more DRY way of doing this.

class Array 
  def id_find id
    self.detect{|element| element.id == id}
  end
end
EmFi
interesting. I suppose thats the same as doing .collect. I was hoping that rails may be hashing the id's under the cover's for a quick lookup.
gmoniey
No. collect will return an array that is the result of evaluating the block for each index of the calling array. Whereas the code in my solution. Returns the one first item in the array for which the block evaluates to true.
EmFi
Ahh...thanks for clearing that up
gmoniey