Hello everyone, I would like to eager load scoped records to avoid queries executed in a loop (huge performance impact). The "scoped" part is what is giving me a hard time. I''m using Rails3 RC. Does anyone have any idea how I can do it? Here is a test case : we have an "Article" and a "Comment" Activerecord models, article has many comments comment belongs to article Comment has a scope defined like this (app/models/comment.rb) : ---------------------------------------------- def recent where ["published_at >= ?", 2.days.ago] end ---------------------------------------------- In the ArticlesController (app/controllers/comments_controller.rb) : ---------------------------------------------- def index @articles = Article.includes(:comments) end ---------------------------------------------- In the view (haml) (app/views/articles/index.html.haml): ---------------------------------------------- - @articles.each do |article| = article.title - article.comments.each do |comment| = comment.body ---------------------------------------------- this works fine and no query is executed when accessing the comments for each articles ("includes" call in the controller handled the eager loading). But if you try to display only the recent comments for each article : ---------------------------------------------- - @articles.each do |article| = article.title - article.comments.recent.each do |recent_comment| = recent_comment.body ---------------------------------------------- Now a query is executed for every article in order to fetch it''s recent articles. What can I write (presumably in the "include" call) to get the eager loading to work in this situation ? Cheers, M-Ryan -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
On Aug 5, 9:48 am, M- Ryan <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Hello everyone, > > I would like to eager load scoped records to avoid queries executed in a > loop (huge performance impact). > > The "scoped" part is what is giving me a hard time.Can you define a scope at class level, instead of defining a method? scope :recent, where ["published_at >= ?", 2.days.ago] Then when you later do article.comments.recent the join/include clauses should be chained together *first*, resulting in max one query per article. Jeff> I''m using Rails3 RC. > > Does anyone have any idea how I can do it? > > Here is a test case : we have an "Article" and a "Comment" Activerecord > models, > > article has many comments > comment belongs to article > > Comment has a scope defined like this (app/models/comment.rb) : > > ---------------------------------------------- > > def recent > where ["published_at >= ?", 2.days.ago] > end > > ---------------------------------------------- > > In the ArticlesController (app/controllers/comments_controller.rb) : > > ---------------------------------------------- > > def index > @articles = Article.includes(:comments) > end > > ---------------------------------------------- > > In the view (haml) (app/views/articles/index.html.haml): > > ---------------------------------------------- > > - @articles.each do |article| > = article.title > - article.comments.each do |comment| > = comment.body > > ---------------------------------------------- > > this works fine and no query is executed when accessing the comments for > each articles ("includes" call in the controller handled the eager > loading). > > But if you try to display only the recent comments for each article : > > ---------------------------------------------- > > - @articles.each do |article| > = article.title > - article.comments.recent.each do |recent_comment| > = recent_comment.body > > ---------------------------------------------- > > Now a query is executed for every article in order to fetch it''s recent > articles. > > What can I write (presumably in the "include" call) to get the eager > loading to work in this situation ? > > Cheers, > > M-Ryan > -- > Posted viahttp://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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Thanks for your replay Jeff. Unfortunately, declaring my scope with the "scope" method instead of a regular method returning an ActiveRecord::Relation doesn''t solve my problem. (it also creates a new one since "2.days.ago" is only evaluated when the app loads the classes and not every time the method is called) I think the includes method should support relations as well as associations (since associations/scopes/relations are so well integrated with eachother in rails 3). That way the following : @articles = Article.includes(:comments => :recent) would build the relation in a way that recent comments are eagerly loaded (instead of complaining that comments have no association named "recent") Cheers, M-Ryan -- 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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Ho-Sheng Hsiao
2010-Aug-06 18:39 UTC
Re: how to ? Rails 3 ActiveRecord eager loading and AREL
On Aug 6, 3:03 am, M- Ryan <li...-fsXkhYbjdPsEEoCn2XhGlw@public.gmane.org> wrote:> Unfortunately, declaring my scope with the "scope" method instead of a > regular method returning an ActiveRecord::Relation doesn''t solve my > problem. (it also creates a new one since "2.days.ago" is only evaluated > when the app loads the classes and not every time the method is called)He made a mistake. It should be: scope :recent, lambda { where ["published_at >= ?", 2.days.ago] }> I think the includes method should support relations as well as > associations (since associations/scopes/relations are so well integrated > with eachother in rails 3). > That way the following : > > @articles = Article.includes(:comments => :recent)Ok, I see. You want to scope the eager-loaded objects. I guess this is a case where Datamapper''s identity map comes in handy. I haven''t tried this yet, but you might be able to put add scopes to the association itself. has_many :recent_comments, :class_name => "Comment", :conditions => ... Hm, though that won''t do the lazy eval. I checked the code for has_many. The finder_sql is constructed the old way, not Arel all the way down. The compromise I can think of is to extend the collection code so it loads all the comments in one batch and insert them into your articles. The other one I can think of is to use AJAX to load the recent comments and have a dedicated controller handle that. It''s probably a better design than trying to load a set of articles and recent comments for all of them, in a single go, then rendering them to the page. Ho-Sheng Hsiao http://ruby-lambda.blogspot.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-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk+unsubscribe@googlegroups.com. For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en.
Reasonably Related Threads
- [PATCH] Access to more Arel predicate types from where condition hash
- ActiveRecord with different Date/Time format
- [PATCH] Support for DB Clusters/Replication in ActiveRecord (RFC)
- eager associations and limit/offset
- Patch for #3438: Eager loading doesn''t respect :order of associations