This project is archived and is in readonly mode.

#1677 ✓resolved
Matt Jankowski

Association proxies using class methods with named scopes

Reported by Matt Jankowski | December 31st, 2008 @ 03:54 PM | in 2.x

I believe this occurs in both 2.0 and 2.2.

When you attempt to chain named_scopes together in a class method, and then call that class method through an association proxy, the conditions from the association proxy are not applied unless the class method ends with a call to #all when using the named scopes. Simple example follows...

Class definitions...



  class Event

    belongs_to :hub

    def self.upcoming_with_all(limit = nil)
      public.ending_after(Time.now.utc).published.limited(limit).ordered.all
    end

    def self.upcoming_without_all(limit = nil)
      public.ending_after(Time.now.utc).published.limited(limit).ordered
    end
  
  end

  class Hub
    has_many :events
  end

Console output...



  >> Hub.first.events.upcoming_with_all(2)
    Hub Load (0.7ms)   SELECT * FROM `hubs` LIMIT 1
    Event Load (1.0ms)   SELECT * FROM `events` WHERE ((((`events`.hub_id = 1) 
    AND (events.published = 1)) AND (events.ends_at > '2008-12-29 21:17:50')) 
    AND ((not events.private))) ORDER BY events.created_on desc LIMIT 2

  >> Hub.first.events.upcoming_without_all(2)
    Hub Load (0.3ms)   SELECT * FROM `hubs` LIMIT 1
    SQL (345.4ms)   SELECT count(*) AS count_all FROM `events` 
    WHERE (((events.published = 1) AND (events.ends_at > '2008-12-29 21:17:55')) 
    AND ((not events.private))) LIMIT 2

Note how the first version, whose class method has an #all call on the end of the scope chain, correctly uses the condition that comes from the association (ie, it limits to a certain hub), but the second version does not.

Comments and changes to this ticket

  • Frederick Cheung

    Frederick Cheung December 31st, 2008 @ 05:00 PM

    I think I understand why this is. I setup User has_many posts, post has a named_scope called active.

    When you do

    
    User.last.posts.active
    

    Then active is called on the association proxy, and method missing on the association proxy knows that if you call :foo on it and :foo is a named scope on the parent then it should call that scope on itself (ie the named scope is called with proxy_scope set to the association proxy)

    When you do

    
    class Post
      def self.class_method
        active
      end
    end
    User.last.posts.class_method
    

    Then the active method is called on class Post, not the association proxy and so the named scope is called with proxy_scope set to Post, not the association proxy.

    The association proxy wraps the call to class_method in a with_scope with the conditions so if class_method does a find then it will execute inside the with_scope block and everything is fine. But if it just invokes a scope upon which a find is done later then that find is executed outside the with_scope and so everything falls to pieces.

  • Diego Algorta

    Diego Algorta February 20th, 2009 @ 01:56 PM

    I think my patch on #1960 fixes this.

  • Repository

    Repository February 25th, 2009 @ 05:13 PM

    • State changed from “new” to “resolved”

    (from [a9aa18fdcdf3146ccbdecff71e52015f26a0f0b7]) Fixed bug that makes named_scopes forgot current scope

    Signed-off-by: rick technoweenie@gmail.com [#1960 #1677 state:resolved] http://github.com/rails/rails/co...

  • csnk

    csnk May 18th, 2011 @ 08:29 AM

    We are the professional clothing manufacturer and clothing supplier, so we manufacture kinds of custom clothing manufacturer. welcome you to come to our china clothing manufacturer and clothing factory.

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>

Referenced by

Pages