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.

AR scopes behave differently than class methods

#6512

Rails 3.0.5:

class User < ActiveRecord::Base
  scope :a, where(:email => "a")
  scope :b, where(:email => "b")
  
  def self.c; where(:email => "c"); end
  def self.d; where(:email => "d"); end
end

# scope + scope
User.a.b.to_sql
# SELECT "users".* FROM "users" WHERE "users"."email" = 'b' - only the last scope is present

# method + scope
User.c.b.to_sql
# SELECT "users".* FROM "users" WHERE "users"."email" = 'b' - only the last scope is present

# scope + method
User.a.c.to_sql
# SELECT "users".* FROM "users" WHERE "users"."email" = 'a' AND "users"."email" = 'c'

# method + method
User.c.d.to_sql
# SELECT "users".* FROM "users" WHERE "users"."email" = 'c' AND "users"."email" = 'd'

Whenever there's a scope at the end of the chain, similar scopes before it are overwritten. When using class methods everything works fine.

Reported by Szymon Nowak · March 3rd, 2011 @ 03:06 PM

State: open
Milestone: none
Assigned to: Aaron Patterson Aaron Patterson
Importance: Low

Activity

  1. Andrew White
    Andrew White
    • State changed from new to wontfix
    • Importance changed from to Low

    This is the intended behavior as looking for an email address equal to two different values will always give an empty result - this section of code is responsible for removing the duplicates. The reason the class methods give the results that they do is they're merging the where values of AR:Relation which are already strings whereas the scope merges hashes.

    March 3rd, 2011 @ 04:34 PM

  2. Szymon Nowak
    Szymon Nowak

    Ok, the example with email was maybe not very fortunate, but in case of WHERE IN clause it really is not consisten:

    class User < ActiveRecord::Base
      scope :a, where(:state => ["active", "confirmed"])
      scope :b, where(:state => ["deleted", "confirmed"])
    end
    

    If you try to use both scopes, it will return only the second one, but when you write it using where method explicitly, or using class methods, you'll get intersection of these 2 sets: WHERE IN ("active", "confirmed") AND WHERE IN ("deleted", "confirmed").

    March 3rd, 2011 @ 04:42 PM

  3. Andrew White
    Andrew White
    • State changed from wontfix to open
    • Assigned user set to Aaron Patterson

    Hmm, looking at this again it looks like another instance of this bug. What do you think Aaron? Removing the code breaks a couple of tests which are specifically testing that the later key overrides the earlier key and it would make it consistent with relation merging.

    March 3rd, 2011 @ 05:31 PM