Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

named_scope does not respect eager loading

#424

class Person
  has_many :messages
end

class Message
  belongs_to :person
  named_scope :unread, :conditions => { :is_read => false }
end

@person = Person.first(:include => :messages) # performs an sql query
@person.messages.unread # performs another sql query. should it?
@person.messages.find_all { |msg| !msg.is_read } # does not perform sql query.
@person.messages.unread.find_all { true } # completely ignores '.unread'. should it?

i'm not sure whether it is a bug or a feature.

is there a way to utilize existing named_scopes to perform filtering on already loaded associations without additional queries?

Reported by Dennis Krupenik · June 16th, 2008 @ 09:24 PM

State: invalid
Milestone: none
Assigned to: nobody
Importance: none

Activity

  1. elDub
    elDub
    • Tag set to eager_loading, named_scope

    I have been battling with this issue as well. I think the problem is more related to 'has_one' relationships though.

    class Document < ActiveRecord::Base
      has_one :revision, :class_name => 'Document', :foreign_key => 'prior_revision_id'
      belongs_to :prior_revision, :class_name => 'Document', :foreign_key => 'prior_revision_id'
      
      named_scope :active, :conditions => { :active => true }
      named_scope :inactive, :conditions => { :active => false }
    end
    

    And then in script/console:

    Loading development environment (Rails 2.1.0)
    >> d1 = Document.create(:active => false, :title => 'd1', :body => 'text')
    => #<Document id: 1, prior_revision_id: nil, title: "d1", body: "text", active: false, created_at: "2008-07-17 14:18:36", updated_at: "2008-07-17 14:18:36">
    >> d2 = d1.create_revision(:active => true, :title => 'd2', :body => 'new text')
    => #<Document id: 2, prior_revision_id: 1, title: "d2", body: "new text", active: true, created_at: "2008-07-17 14:19:14", updated_at: "2008-07-17 14:19:14">
    
    >> doc = Document.find(1, :include => :revision)
    => #<Document id: 1, prior_revision_id: nil, title: "d1", body: "text", active: false, created_at: "2008-07-17 14:18:36", updated_at: "2008-07-17 14:18:36">
    >> doc.revision
    => #<Document id: 2, prior_revision_id: 1, title: "d2", body: "new text", active: true, created_at: "2008-07-17 14:19:14", updated_at: "2008-07-17 14:19:14">
    
    >> ns_doc = Document.inactive.find(:all, :include => :revision)[0]
    => #<Document id: 1, prior_revision_id: nil, title: "d1", body: "text", active: false, created_at: "2008-07-17 14:18:36", updated_at: "2008-07-17 14:18:36">
    >> ns_doc.revision
    => nil
    

    Note how the attempt to use eager loading within a named scope request causes the same document (id: 1) to NOT be able to access it's revision.

    July 17th, 2008 @ 03:24 PM

  2. elDub
    elDub

    Please forgive/ignore my prior post. After re-thinking it, it is a different issue which I will create a new post for.

    July 17th, 2008 @ 03:37 PM

  3. Tarmo Tänav
    Tarmo Tänav
    • State changed from new to invalid
    • Tag changed from eager_loading, named_scope to eager_loading, named_scope

    Since conditions on named_scope's can be arbitrarily complex SQL snippets it is impossible to filter the association by the named scope in AR alone, making an exception for simple hash based conditions does not seem likely to happen.

    September 18th, 2008 @ 06:51 AM