Consider this situation class Property < ActiveRecord::Base has_many :photos end Now if you reference: @property.photos[0].property It reloads the property. I''m looking for a way to suggest the association directly to the associated objects. I know this example seems contrived, but it''s just a simplification. In actuality my Photo model has a method that looks like this: class Photo < ActiveRecord::Base def public_filename File.join("images", property.idx.name, filename) end end Not only does this result in n+1 queries, but it actually results in 2n +1, even though I am eager loading all the necessary data up front. I can think of a lot of ways to solve this, but to cleanly solve it requires somehow suggesting the existing loaded @property object to the photo.property assocation. If there''s no way to do this, maybe there should be... --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
dasil003 wrote:> Consider this situation > > class Property < ActiveRecord::Base > has_many :photos > end > > Now if you reference: > > @property.photos[0].property > > It reloads the property. I''m looking for a way to suggest the > association directly to the associated objects. > > I know this example seems contrived, but it''s just a simplification. > In actuality my Photo model has a method that looks like this: > > class Photo < ActiveRecord::Base > def public_filename > File.join("images", property.idx.name, filename) > end > end > > Not only does this result in n+1 queries, but it actually results in 2n > +1, even though I am eager loading all the necessary data up front. > > I can think of a lot of ways to solve this, but to cleanly solve it > requires somehow suggesting the existing loaded @property object to > the photo.property assocation. If there''s no way to do this, maybe > there should be...Yes, back associations aren''t currently found and set automatically. You can have it done automatically for your association: class Property < ActiveRecord::Base has_many :photos def photos_with_back_links(*params) photos_without_back_links(*params).each { |p| p.property = self } end alias_method_chain :photos, :back_links end -- 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 -~----------~----~----~----~------~----~------~--~---
Very cool solution, looking up alias_method_chain was well worth it. There is one problem when calling a method on the association proxy that doesn''t actually return an array of Photos such as: @property.photos.count I dug into AssocationProxy and it''s subclasses to figure out how best to make this work. I think something like: class Property < ActiveRecord::Base has_many :photos def photos_with_back_links(*params) result = photos_without_back_links(*params) result.each { |p| p.set_property_target = self } if result.is_a? (Array) end alias_method_chain :photos, :back_links end will work generally, although it could still choke on methods that return an array that''s not a list of photos... is it worth putting a conditional inside the loop? On Jun 11, 10:22 pm, Mark Reginald James <m...-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> wrote:> dasil003 wrote: > > Consider this situation > > > class Property < ActiveRecord::Base > > has_many :photos > > end > > > Now if you reference: > > > @property.photos[0].property > > > It reloads the property. I''m looking for a way to suggest the > > association directly to the associated objects. > > > I know this example seems contrived, but it''s just a simplification. > > In actuality my Photo model has a method that looks like this: > > > class Photo < ActiveRecord::Base > > def public_filename > > File.join("images", property.idx.name, filename) > > end > > end > > > Not only does this result in n+1 queries, but it actually results in 2n > > +1, even though I am eager loading all the necessary data up front. > > > I can think of a lot of ways to solve this, but to cleanly solve it > > requires somehow suggesting the existing loaded @property object to > > the photo.property assocation. If there''s no way to do this, maybe > > there should be... > > Yes, back associations aren''t currently found and set automatically. > You can have it done automatically for your association: > > class Property < ActiveRecord::Base > has_many :photos > def photos_with_back_links(*params) > photos_without_back_links(*params).each { |p| p.property = self } > end > alias_method_chain :photos, :back_links > end > > -- > 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 -~----------~----~----~----~------~----~------~--~---
Actually the other methods don''t work at all. This technique can''t really solve the problem satisfactorily because the array isn''t loaded until a method is called on the proxy that needs it. This alias- chaining is too early. The method to chain is find_target in AssociationCollection, but that is considerably trickier to pull off... On Jun 13, 4:57 pm, dasil003 <gabrie...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Very cool solution, looking up alias_method_chain was well worth it. > > There is one problem when calling a method on the association proxy > that doesn''t actually return an array of Photos such as: > > @property.photos.count > > I dug into AssocationProxy and it''s subclasses to figure out how best > to make this work. I think something like: > > class Property < ActiveRecord::Base > has_many :photos > def photos_with_back_links(*params) > result = photos_without_back_links(*params) > result.each { |p| p.set_property_target = self } if result.is_a? > (Array) > end > alias_method_chain :photos, :back_links > end > > will work generally, although it could still choke on methods that > return an array that''s not a list of photos... is it worth putting a > conditional inside the loop? > > On Jun 11, 10:22 pm, Mark Reginald James <m...-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> wrote: > > > dasil003 wrote: > > > Consider this situation > > > > class Property < ActiveRecord::Base > > > has_many :photos > > > end > > > > Now if you reference: > > > > @property.photos[0].property > > > > It reloads the property. I''m looking for a way to suggest the > > > association directly to the associated objects. > > > > I know this example seems contrived, but it''s just a simplification. > > > In actuality my Photo model has a method that looks like this: > > > > class Photo < ActiveRecord::Base > > > def public_filename > > > File.join("images", property.idx.name, filename) > > > end > > > end > > > > Not only does this result in n+1 queries, but it actually results in 2n > > > +1, even though I am eager loading all the necessary data up front. > > > > I can think of a lot of ways to solve this, but to cleanly solve it > > > requires somehow suggesting the existing loaded @property object to > > > the photo.property assocation. If there''s no way to do this, maybe > > > there should be... > > > Yes, back associations aren''t currently found and set automatically. > > You can have it done automatically for your association: > > > class Property < ActiveRecord::Base > > has_many :photos > > def photos_with_back_links(*params) > > photos_without_back_links(*params).each { |p| p.property = self } > > end > > alias_method_chain :photos, :back_links > > end > > > -- > > 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 -~----------~----~----~----~------~----~------~--~---
class Property < ActiveRecord::Base has_many :photos do def hydrate each {|x| x.set_property_target @owner} end end end Property.find(:all, :limit => 10, :include => :photos).each {|x| x.photos.hydrate} Trevor On 6/13/07, dasil003 <gabriel.d-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > Actually the other methods don''t work at all. This technique can''t > really solve the problem satisfactorily because the array isn''t loaded > until a method is called on the proxy that needs it. This alias- > chaining is too early. > > The method to chain is find_target in AssociationCollection, but that > is considerably trickier to pull off... > > On Jun 13, 4:57 pm, dasil003 <gabrie...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > Very cool solution, looking up alias_method_chain was well worth it. > > > > There is one problem when calling a method on the association proxy > > that doesn''t actually return an array of Photos such as: > > > > @property.photos.count > > > > I dug into AssocationProxy and it''s subclasses to figure out how best > > to make this work. I think something like: > > > > class Property < ActiveRecord::Base > > has_many :photos > > def photos_with_back_links(*params) > > result = photos_without_back_links(*params) > > result.each { |p| p.set_property_target = self } if result.is_a? > > (Array) > > end > > alias_method_chain :photos, :back_links > > end > > > > will work generally, although it could still choke on methods that > > return an array that''s not a list of photos... is it worth putting a > > conditional inside the loop? > > > > On Jun 11, 10:22 pm, Mark Reginald James <m...-bzGI/hKkdgQnC9Muvcwxkw@public.gmane.org> wrote: > > > > > dasil003 wrote: > > > > Consider this situation > > > > > > class Property < ActiveRecord::Base > > > > has_many :photos > > > > end > > > > > > Now if you reference: > > > > > > @property.photos[0].property > > > > > > It reloads the property. I''m looking for a way to suggest the > > > > association directly to the associated objects. > > > > > > I know this example seems contrived, but it''s just a simplification. > > > > In actuality my Photo model has a method that looks like this: > > > > > > class Photo < ActiveRecord::Base > > > > def public_filename > > > > File.join("images", property.idx.name, filename) > > > > end > > > > end > > > > > > Not only does this result in n+1 queries, but it actually results in 2n > > > > +1, even though I am eager loading all the necessary data up front. > > > > > > I can think of a lot of ways to solve this, but to cleanly solve it > > > > requires somehow suggesting the existing loaded @property object to > > > > the photo.property assocation. If there''s no way to do this, maybe > > > > there should be... > > > > > Yes, back associations aren''t currently found and set automatically. > > > You can have it done automatically for your association: > > > > > class Property < ActiveRecord::Base > > > has_many :photos > > > def photos_with_back_links(*params) > > > photos_without_back_links(*params).each { |p| p.property = self } > > > end > > > alias_method_chain :photos, :back_links > > > end > > > > > -- > > > We develop, watch us RoR, in numbers too big to ignore. > > > > >-- -- Trevor Squires http://somethinglearned.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 -~----------~----~----~----~------~----~------~--~---
dasil003 wrote:> Actually the other methods don''t work at all. This technique can''t > really solve the problem satisfactorily because the array isn''t loaded > until a method is called on the proxy that needs it. This alias- > chaining is too early.Yes, I''d only considered the case where the unadorned whole collection was being fetched, not the use of proxy methods. I now have a better understanding of the delayed loading the proxy implements by defining the respond_to? method. The "each" triggers the load of the whole association, so rather than aliasing the association name you''d have to have a separate method for the back-linked version, only used when you want the whole collection. -- 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 -~----------~----~----~----~------~----~------~--~---