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 -~----------~----~----~----~------~----~------~--~---