Why has_many doesn''t set target for objects in its collection? E.g. when class Author < ActiveRecord; has_many :posts; end class Post < ActiveRecord; belongs_to :author; end then some_author.posts.each {|p| puts p.author.name} will require additional queries to fetch author for each post. Could some option to has_many be added to pre-fill the target (in this case set_author_target for each post)? Something like: module ActiveRecord module Associations # :nodoc: module ClassMethods # When called with <tt>:fill_target => name</tt> it will fill targets in each object in association # E.g.: when Author <tt>has_many :posts, :fill_target => "author"</tt> # then <tt>some_author.posts.each {|m| m.author.name }</tt> will not require aditional db queries to fetch author for each post # (it will use the +some_author+ already from memory) # # Two methods are created additionally, for the example above it will be +posts_with_author+ and +posts_without_author+, # where just +posts+ is the same as +posts_with_author+ def has_many_with_fill_target(association_id, options = {}, &extension) fill_target = options.delete(:fill_target) has_many_without_fill_target(association_id, options, &extension) if fill_target module_eval do define_method("#{association_id}_with_#{fill_target}") do | *args| returning( send("#{association_id}_without_#{fill_target}", *args) ) {| p| p.each {|m| m.send("set_#{fill_target}_target", self) } } end alias_method_chain association_id, fill_target end end end alias_method_chain :has_many, :fill_target end end end --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Wait a min.. some_author.posts.each {|p| puts p.author.name} p.author.name == some_author.name ! On 8/7/07, paccator <paccator@gmail.com> wrote:> > Why has_many doesn''t set target for objects in its collection? > > E.g. when > > class Author < ActiveRecord; has_many :posts; end > class Post < ActiveRecord; belongs_to :author; end > > then > > some_author.posts.each {|p| puts p.author.name} > > will require additional queries to fetch author for each post. > > > Could some option to has_many be added to pre-fill the target (in this > case set_author_target for each post)? > > > > Something like: > > module ActiveRecord > module Associations # :nodoc: > module ClassMethods > > # When called with <tt>:fill_target => name</tt> it will fill > targets in each object in association > # E.g.: when Author <tt>has_many :posts, :fill_target => > "author"</tt> > # then <tt>some_author.posts.each {|m| m.author.name }</tt> will > not require aditional db queries to fetch author for each post > # (it will use the +some_author+ already from memory) > # > # Two methods are created additionally, for the example above it > will be +posts_with_author+ and +posts_without_author+, > # where just +posts+ is the same as +posts_with_author+ > > def has_many_with_fill_target(association_id, options = {}, > &extension) > fill_target = options.delete(:fill_target) > has_many_without_fill_target(association_id, options, > &extension) > > if fill_target > module_eval do > define_method("#{association_id}_with_#{fill_target}") do | > *args| > > returning( send("#{association_id}_without_#{fill_target}", *args) ) {| > p| p.each {|m| m.send("set_#{fill_target}_target", self) } } > end > alias_method_chain association_id, fill_target > end > end > end > > alias_method_chain :has_many, :fill_target > > end > end > end > > > > >-- Cheers! - Pratik http://m.onkey.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
This mailing list is meant for discussion about implementation details of Rails only. You can post support requests to Rails Talk [1] or #rubyonrails on freenode. [1] http://groups.google.com/group/rubyonrails-talk On Aug 7, 2007, at 2:44, paccator wrote:> > Why has_many doesn''t set target for objects in its collection? > > E.g. when > > class Author < ActiveRecord; has_many :posts; end > class Post < ActiveRecord; belongs_to :author; end > > then > > some_author.posts.each {|p| puts p.author.name} > > will require additional queries to fetch author for each post.That said, some_author.posts.find(:all, :include => :author).each { | p| puts p.author.name } will do a JOIN for you. Although that shouldn''t be necessary if you put some_author in an instance variable and read it from there. Manfred --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
Sorry, but I thought it is about Rails implementation details, has_many implementation details. On Aug 7, 3:01 pm, Manfred Stienstra <manf...@gmail.com> wrote:> This mailing list is meant for discussion about implementation > details of Rails only. You can post support requests to Rails Talk > [1] or #rubyonrails on freenode. > > [1]http://groups.google.com/group/rubyonrails-talk > > On Aug 7, 2007, at 2:44, paccator wrote: > > > > > Why has_many doesn''t set target for objects in its collection? > > > E.g. when > > > class Author < ActiveRecord; has_many :posts; end > > class Post < ActiveRecord; belongs_to :author; end > > > then > > > some_author.posts.each {|p| puts p.author.name} > > > will require additional queries to fetch author for each post. > > That said, some_author.posts.find(:all, :include => :author).each { | > p| puts p.author.name } will do a JOIN for you. Although that > shouldn''t be necessary if you put some_author in an instance variable > and read it from there. > > ManfredThat said, :include is not a solution, cause it also unnecessarily makes bigger query just to fetch object which I already have in memory. Instant variable is not enough. My example was intentionally simple just to show what I mean. Imagine that I have few authors somewhere, and I collect their posts, and this posts list is accessed from outside. Also I was more hoping to see opinion about suggested extension to has_many. paccator --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
> That said, :include is not a solution, cause it also unnecessarily > makes bigger query just to fetch object which I already have in > memory. > Instant variable is not enough. My example was intentionally simple > just to show what I mean. > Imagine that I have few authors somewhere, and I collect their posts, > and this posts list is accessed from outside. > Also I was more hoping to see opinion about suggested extension to > has_many.ActiveRecord on edge rails has a cache that is active in ActionController requests so this shouldn''t be a problem. I also have a plugin that takes a slightly different route in caching frequently accessed records in a single request. http://activereload.net/2007/5/23/spend-less-time-in-the-database-and-more-time-outdoors -- 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: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
On 8/8/07, paccator <paccator@gmail.com> wrote:> > Why has_many doesn''t set target for objects in its collection? > > E.g. when > > class Author < ActiveRecord; has_many :posts; end > class Post < ActiveRecord; belongs_to :author; end > > then > > some_author.posts.each {|p| puts p.author.name} > > will require additional queries to fetch author for each post. > > > Could some option to has_many be added to pre-fill the target (in this > case set_author_target for each post)?It''s definitely possible to do some form of bidirectional association at present. You just need to either calculate or configure the belongs_to association which is the inverse of the has_many. For some simple cases calculation could work. However it starts to get quite tricky when the has_many has :conditions or :includes applied, or if there are multiple has_many associations etc. However if you whip up a plugin or patch which implements this, I''m sure there are people who''d help out with testing it. It''s a surprising gotcha for some users. Having said that, rick''s context plugin implements an identity map, so it could be worth investigating first. -- Cheers Koz --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---
On Aug 7, 2007, at 3:25, paccator wrote:> > Sorry, but I thought it is about Rails implementation details, > has_many implementation details.Sorry, I think I misunderstood you''re problem. Manfred --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To post to this group, send email to rubyonrails-core@googlegroups.com To unsubscribe from this group, send email to rubyonrails-core-unsubscribe@googlegroups.com For more options, visit this group at http://groups.google.com/group/rubyonrails-core?hl=en -~----------~----~----~----~------~----~------~--~---