This project is archived and is in readonly mode.

#6512 open
Szymon Nowak

AR scopes behave differently than class methods

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

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.

Comments and changes to this ticket

  • Andrew White

    Andrew White March 3rd, 2011 @ 04:34 PM

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

  • Szymon Nowak

    Szymon Nowak March 3rd, 2011 @ 04:42 PM

    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").

  • Andrew White

    Andrew White March 3rd, 2011 @ 05:31 PM

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

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