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.

Make named_scopes remember the current scope when defined

#1960

Given the following code:


class Post < ActiveRecord::Base
  belongs_to :topic
  belongs_to :author

  named_scope :published, :conditions => {:published => true}
  named_scope :by_author, lambda {|a| {:conditions => {:author_id => a.id}}}
  named_scope :ranked, :order => "posts.rank DESC"
  named_scope :limit, lambda {|limit| {:limit => limit}}

  def self.top_by(an_author)
    published.by_author(an_author).ranked.limit(10)
  end
end

class Topic < ActiveRecord::Base
  has_many :posts
end

class Author < ActiveRecord::Base
  has_many :posts
end

Without this patch, @topic.posts.top_by(@author) generates the exact same query than Post.top_by(@author), totally ignoring the scope added by the has_many :posts in Topic. That's because that scope is being removed from the stacked scopes after the top_by execution where the chained scopes where defined, but before the chained scopes are really executing thus firing the Scope#load_found call.

With this patch, the current scope is saved in the Scope instance at instantiation time, so it can be re-applied when executed.

Reported by Diego Algorta · February 13th, 2009 @ 07:40 AM

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

Activity

  1. Diego Algorta
    Diego Algorta

    Forgot to say that, as of now, this patch applies cleanly in both 2-2-stable and master branches.

    February 13th, 2009 @ 07:42 AM

  2. ronin-278 (at lighthouseapp)
  3. Paweł Kondzior
  4. Ryan Berdeen
    Ryan Berdeen

    +1

    This is a dangerous bug I just spent hours tracking down myself. Scopes should never disappear without warning.

    February 17th, 2009 @ 07:04 AM

  5. Diego Algorta
    Diego Algorta
    • Tag changed from 2.2-stable, activerecord, association_proxy, master, named_scope, patch to 2.2-stable, activerecord, association_proxy, master, named_scope, patch, verified

    Adding the verified tag now that 3 people have voted positively.

    February 17th, 2009 @ 05:08 PM

  6. Ryan Berdeen
    Ryan Berdeen

    I believe this was previously reported as #1770, which doesn't have a patch.

    February 17th, 2009 @ 06:12 PM

  7. Ryan Berdeen
    Ryan Berdeen

    Whoops, looks like #1770 has somewhat similar symptoms, but its cause is probably in association_collection or elsewhere, not named_scope. This patch doesn't fix it.

    February 18th, 2009 @ 01:36 AM

  8. Matt Jankowski
  9. Diego Algorta
    Diego Algorta

    Yes. This patch should fix #1677 too. It's the same problem.

    February 20th, 2009 @ 01:45 PM

  10. Repository
    Repository
    • 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...

    February 25th, 2009 @ 05:13 PM

  11. Rick
    Rick
    • State changed from resolved to open

    Hmm I get this failure on master:

    
      1) Failure:
    test_named_scope(DefaultScopingTest)
        [./test/cases/method_scoping_test.rb:602:in `test_named_scope'
         ./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `__send__'
         ./test/cases/../../../activesupport/lib/active_support/testing/setup_and_teardown.rb:57:in `run']:
    <[9000,
     150000,
     100000,
     100000,
     100000,
     100000,
     100000,
     100000,
     100000,
     100000,
     80000]> expected but was
    <[150000,
     100000,
     100000,
     100000,
     100000,
     100000,
     100000,
     100000,
     100000,
     80000,
     9000]>.
    

    February 25th, 2009 @ 05:17 PM

  12. Rick
    Rick
    • State changed from open to resolved

    Ah, the test was bad:

    
       def test_named_scope
    -    expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary }
    +    expected = Developer.find(:all, :order => 'salary DESC, name DESC').collect { |dev| dev.salary }
         received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.salary }
         assert_equal expected, received
       end
    

    It was leaving out the DeveloperOrderedBySalary default scope :order => 'salary DESC'. So, this patch actually fixed that failing test, and probably a bunch of other issues mixing default and named scopes.

    February 25th, 2009 @ 05:29 PM

  13. Alexander Podgorbunsky
    Alexander Podgorbunsky

    Unfortunately, the test was failing right and then broken -- see #2346

    March 26th, 2009 @ 01:20 PM