Hi, If I eagerly load a collection during the initial find, do scoped find_by_ calls later _always_ use sql? What is the best pattern to use to not do another db trip? Is there some specialized rails method to handle this case? eg Author has_many :books larry = Author.find_by_name(''larry'', :include => :books) ruby = larry.books.find_by_title(''Ruby'') # does this ALWAYS do a db call? # Is the following the best way to get the one (or nil) book? temp = larry.books.select{|book| book.title == ''ruby''} ruby = temp.size == 1 ? temp[0] : nil Thank you for your comments and time, Larry -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Larry Kluger wrote:> If I eagerly load a collection during the initial find, do scoped > find_by_ calls later _always_ use sql?Yes.> What is the best pattern to use to not do another db trip? > Is there some specialized rails method to handle this case? > > eg > Author > has_many :books > > larry = Author.find_by_name(''larry'', :include => :books) > > ruby = larry.books.find_by_title(''Ruby'') # does this ALWAYS do a db > call? > > # Is the following the best way to get the one (or nil) book? > temp = larry.books.select{|book| book.title == ''ruby''} > ruby = temp.size == 1 ? temp[0] : nilYes. Or ruby = larry.books.detect {|book| book.title == ''ruby''} -- We develop, watch us RoR, in numbers too big to ignore. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Hi Mark, Thanks for your time, much appreciated.> > Yes. Or ruby = larry.books.detect {|book| book.title == ''ruby''} >Regards, Larry -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Larry Kluger wrote:> > Hi, > > If I eagerly load a collection during the initial find, do scoped > find_by_ calls later _always_ use sql? > > What is the best pattern to use to not do another db trip? > Is there some specialized rails method to handle this case? > > eg > Author > has_many :books > > larry = Author.find_by_name(''larry'', :include => :books) > > ruby = larry.books.find_by_title(''Ruby'') # does this ALWAYS do a db > call? > > # Is the following the best way to get the one (or nil) book? > temp = larry.books.select{|book| book.title == ''ruby''} > ruby = temp.size == 1 ? temp[0] : nil > > Thank you for your comments and time, > > LarrySense you now have all Larry''s books in memory it is probably better to search through the memory using ruby calls like: ruby = larry.books.detect {|book| book.title == ''ruby''} On the other hand ruby is a comparatively slow next most database engines. If you have a large number of books by Larry (or authors in general) AND you know you only need to find a small finite set of them (like one) The database may be faster then the Ruby script interrupter at doing what it does best -- finding a subset of items in a table. Eager loading is best used when you know you will need all or most of the related information in another table, (eg All the books Larry wrote) or information in a related table for every member of the first. (eg, the best selling book for each Author) -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
dblack-TKXtfPMJ4Ozk1uMJSBkQmQ@public.gmane.org
2007-Aug-20 11:25 UTC
Re: find_by_ always uses sql?
Hi -- On Mon, 20 Aug 2007, John Miller wrote:> > Larry Kluger wrote: >> >> Hi, >> >> If I eagerly load a collection during the initial find, do scoped >> find_by_ calls later _always_ use sql? >> >> What is the best pattern to use to not do another db trip? >> Is there some specialized rails method to handle this case? >> >> eg >> Author >> has_many :books >> >> larry = Author.find_by_name(''larry'', :include => :books) >> >> ruby = larry.books.find_by_title(''Ruby'') # does this ALWAYS do a db >> call? >> >> # Is the following the best way to get the one (or nil) book? >> temp = larry.books.select{|book| book.title == ''ruby''} >> ruby = temp.size == 1 ? temp[0] : nil >> >> Thank you for your comments and time, >> >> Larry > > Sense you now have all Larry''s books in memory it is probably better to > search through the memory using ruby calls like: > > ruby = larry.books.detect {|book| book.title == ''ruby''}find and find_by_* on a collection are smart, though: they get rolled into one database query with the collection query itself. For example: $ ./script/console Loading development environment. >> f = Food.find(:first) => #<Food:0x3544f04 @attributes={"name"=>"bread", "id"=>"1", "food_group_id"=>"2"}> >> f.ingredients.find_by_description("flour") => #<Ingredient:0x3523c28 @attributes={"id"=>"3", "description"=>"flour", "food_id"=>"1"}> Here''s the query log: Food Load (0.000726) SELECT * FROM foods LIMIT 1 Ingredient Load (0.000394) SELECT * FROM ingredients WHERE (ingredients.food_id = 1) AND (ingredients."description" = ''flour'') LIMIT 1 Notice how the second select combines two where clauses, so the whole collection isn''t loaded into memory. The find_by_* methods have some overhead, though, since they have to pass through method_missing. You can also do: f.ingredients.find(:first, :conditions => "description = ''flour''") which won''t have that overhead. Of course, find_by_* is nice and concise, so it''s OK for cases where you''re not looking to tweak performance. David -- * Books: RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242) RUBY FOR RAILS (http://www.manning.com/black) * Ruby/Rails training & consulting: Ruby Power and Light, LLC (http://www.rubypal.com) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---