views:

454

answers:

2

Is there any way to eager load a named_scope from an association?

I have my Article model:

class Article < ActiveRecord::Base
  has_many :comments
end

and my Comment model:

class Comment < ActiveRecord::Base
  belongs_to :article

  named_scope :approved, :conditions => { :approved => true }
  named_scope :unapproved, :conditions => { :approved => false }
end

I could eager load all comments for an article with:

@article = Article.find(params[:id], :include => :comments)

How can I do the same, but only for approved comments?

+2  A: 
Ryan Briones
If I understood the blog post correctly, that would give me the scoped articles with all their comments. It's equivalent to: Article.approved.all(:include => :comments). What I was looking for was scoping the comments, so that each article only eager loads its approved comments, not all of them.
Daniel Perez Alvarez
A: 

The other answer didn't work for me since I have to load many associations and associations of those associations on some models. I found I had two options, change the association to have conditions and thus make an association for each scope I wanted or turn them into methods on the class that had the has_many association. I needed to do something along the lines of:

@newspaper = Newspaper.find params[:id], :include => {
  :articles => {
    :author => true,
    :source => true
  }
}

So in my example I changed:

class Newspaper < ActiveRecord::Base
  has_many :articles
end

class Article
  belongs_to :newspaper
  belongs_to :author
  has_one :source

  named_scope :private, :conditions => { :private => true }
  named_scope :public, :conditions => { :private => false }
end

to:

class Newspaper < ActiveRecord::Base
  has_many :articles

  def articles_public
    articles.reject &:private
  end

  def articles_private
    articles.select &:private
  end
end

class Article
  belongs_to :newspaper
  belongs_to :author
  has_one :source
end

I found this way to be preferable since I can now eager load articles when finding a newspaper and just change all article.private to article_private. Had I created two associations like:

has_many :articles_private, :class_name => 'Article', :conditions {:private => true}
has_many :articles_public, :class_name => 'Article', :conditions {:private => false}

I would have to eager load them both in cases where I needed all associated articles.

Aaron