Let''s say we have two models with a plain has_many/belongs_to relationship. class Driver has_one :car end class Car belongs_to :driver end The question is this: Why isn''t the car''s parent driver cached when we eager load it? So the following snippet (as impractical as it is, it''s just an example) would just result in one hit (as opposed to ActiveRecord''s current behavior, which hits the db each time that #driver is called). @driver = Driver.find(:first, :include => :car) @driver.car.driver.car.driver.car.driver.car Is there a reason for the current behavior? --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
On Jan 30, 2008 9:32 AM, Pat Nakajima <patnakajima-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Let''s say we have two models with a plain has_many/belongs_to > relationship. > > class Driver > has_one :car > end > > class Car > belongs_to :driver > end > > The question is this: Why isn''t the car''s parent driver cached when we > eager load it? So the following snippet (as impractical as it is, it''s > just an example) would just result in one hit (as opposed to > ActiveRecord''s current behavior, which hits the db each time that > #driver is called). > > @driver = Driver.find(:first, :include => :car) > @driver.car.driver.car.driver.car.driver.car > > Is there a reason for the current behavior?Are you using query caching? That should only be maybe 3 queries tops: Driver.find # eager include query @car.driver # belongs_to query @driver.car # has_one query After that, the queries should be repeating and you won''t hit the database anymore. Even then, each association call is creating a new ruby object, even if that query is cached. I have a plugin that enables a simple identity map for ActiveRecord within the context of a controller action: git://activereload.net/active_record_context.git . Every time a record is fetched from the database, it is stored in a global hash by ID. Future requests to receive that record will instead receive the exact same ruby object. Driver.find 1 # query Driver.find 1 # ID map Driver.find 1 # ID map The cool thing is you can preload from large queries: Driver.find :all # query Driver.find 1 # ID map So, you can select all the drivers and all the cars for those drivers in a single query: @drivers = Driver.find :all Car.find :all, :conditions => {:driver_id => @drivers.collect(&:id)} @drivers.each do |driver| driver.car # preloaded in the Car.find query end That''s all fine and dandy, but this won''t work for has_one associations since the query is by driver_id. The plugin''s identity map only indexes records by their primary key. There''s a good chance this plugin will be finding its way into the next release of Rails. -- Rick Olson http://lighthouseapp.com http://weblog.techno-weenie.net http://mephistoblog.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 -~----------~----~----~----~------~----~------~--~---
On Jan 30, 2008, at 10:54 AM, Rick Olson wrote:> > On Jan 30, 2008 9:32 AM, Pat Nakajima <patnakajima-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: >> >> Let''s say we have two models with a plain has_many/belongs_to >> relationship. >> >> class Driver >> has_one :car >> end >> >> class Car >> belongs_to :driver >> end >> >> The question is this: Why isn''t the car''s parent driver cached when >> we >> eager load it? So the following snippet (as impractical as it is, >> it''s >> just an example) would just result in one hit (as opposed to >> ActiveRecord''s current behavior, which hits the db each time that >> #driver is called). >> >> @driver = Driver.find(:first, :include => :car) >> @driver.car.driver.car.driver.car.driver.car >> >> Is there a reason for the current behavior? > > Are you using query caching? That should only be maybe 3 queries > tops: > > Driver.find # eager include query > @car.driver # belongs_to query > @driver.car # has_one query > > After that, the queries should be repeating and you won''t hit the > database anymore. Even then, each association call is creating a new > ruby object, even if that query is cached. > > I have a plugin that enables a simple identity map for ActiveRecord > within the context of a controller action: > git://activereload.net/active_record_context.git . Every time a > record is fetched from the database, it is stored in a global hash by > ID. Future requests to receive that record will instead receive the > exact same ruby object. > > Driver.find 1 # query > Driver.find 1 # ID map > Driver.find 1 # ID map > > The cool thing is you can preload from large queries: > > Driver.find :all # query > Driver.find 1 # ID map > > So, you can select all the drivers and all the cars for those drivers > in a single query: > > @drivers = Driver.find :all > Car.find :all, :conditions => {:driver_id => @drivers.collect(&:id)} > @drivers.each do |driver| > driver.car # preloaded in the Car.find query > end > > That''s all fine and dandy, but this won''t work for has_one > associations since the query is by driver_id. The plugin''s identity > map only indexes records by their primary key. There''s a good chance > this plugin will be finding its way into the next release of Rails.Rick, thanks for this explanation. I''m wondering whether the OP''s question was more related to the use case: - I have a Driver - Who has a car - And I want to know what drivers also have that car - And I want to know all the cars all of those drivers have Driver.find(:first).car.drivers.cars Question to OP: Was this actually what you had in mind or did I misread? --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---