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 fails when accessed through a class method over an association

#1920

When accessing a class method, that calls a named scope, through an association collection, the association scope seems to be lost.

Given

Layer
  has_many :items

Item
  named_scope :published, lambda  { {:conditions => ['items.published_at < ?', Time.now.utc] } }

  def.self find_v1
    all
  end

  def.self find_v2
    published
  end

end

From the console:

> l = Layer.find :first

> l.items.find_v1
SELECT * FROM "items" WHERE ("items".layer_id = 1)

> l.items.find_v2 
SELECT * FROM "items" WHERE (items.published_at < '2009-02-09 15:03:18')

This is where it goes wrong ("items".layer_id = 1) is missing!

> l.items.published
SELECT * FROM "items" WHERE ("items".layer_id = 1) AND (items.published_at < '2009-02-09 15:06:37')

Accessing the named scope directly works perfectly fine

Versions: Rails 2.3.0 (same issue in 2.2.2) ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0] sqlite3 -version 3.6.10

Reported by unders · February 9th, 2009 @ 03:19 PM

State: duplicate
Milestone: 2.x
Assigned to: nobody
Importance: none

Activity

  1. Daniel Guettler
    Daniel Guettler

    Looks like the scoped_methods get popped before the query is actually executed. The call graph for l.items.find_v2 and l.items.published is actually quite different and I couldn't get my head around it to figure out how to fix this the right way. However applying this change to the named_scope.rb file fixes the issue and doesn't brake any existing tests in rails version 2.2.2. I don't consider this at proper patch just as a temp fix in case someone needs it.

    
    --- a/activerecord/lib/active_record/named_scope.rb
    +++ b/activerecord/lib/active_record/named_scope.rb
    @@ -114,6 +114,7 @@ module ActiveRecord
             [options[:extend]].flatten.each { |extension| extend extension } if options[:extend]
             extend Module.new(&block) if block_given?
             @proxy_scope, @proxy_options = proxy_scope, options.except(:extend)
    +        @scoped_methods = proxy_scope.send(:scoped_methods).dup
           end
     
           def reload
    @@ -166,9 +167,11 @@ module ActiveRecord
             if scopes.include?(method)
               scopes[method].call(self, *args)
             else
    -          with_scope :find => proxy_options, :create => proxy_options[:conditions].is_a?(Hash) ?  proxy_options[:conditions] : {} do
    -            method = :new if method == :build
    -            proxy_scope.send(method, *args, &block)
    +          with_scope(@scoped_methods.last || {}) do
    +            with_scope :find => proxy_options, :create => proxy_options[:conditions].is_a?(Hash) ?  proxy_options[:conditions] : {} do
    +              method = :new if method == :build
    +              proxy_scope.send(method, *args, &block)
    +            end
               end
             end
           end
    

    February 26th, 2009 @ 05:46 AM

  2. Daniel Guettler
    Daniel Guettler

    Ah actually this bug is already resolved in couple other tickets. E.g. #1960

    February 26th, 2009 @ 05:58 AM

  3. CancelProfileIsBroken
    CancelProfileIsBroken
    • State changed from new to duplicate

    Resolved by #1960

    August 5th, 2009 @ 02:11 PM