This project is archived and is in readonly mode.

#1920 ✓duplicate
unders

named_scope fails when accessed through a class method over an association

Reported by unders | February 9th, 2009 @ 03:19 PM | in 2.x

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

Comments and changes to this ticket

  • Daniel Guettler

    Daniel Guettler February 26th, 2009 @ 05:46 AM

    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
    
  • Daniel Guettler

    Daniel Guettler February 26th, 2009 @ 05:58 AM

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

  • CancelProfileIsBroken

    CancelProfileIsBroken August 5th, 2009 @ 02:11 PM

    • State changed from “new” to “duplicate”

    Resolved by #1960

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2 style="font-size: 14px">Tickets have moved to Github</h2>

The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>

Pages