8

I'm having some trouble getting scoping to work correctly in rails.

My models:

class User < ActiveRecord::Base
  default_scope :conditions => 'users.deleted_at IS NULL'


class Feed < ActiveRecord::Base
  belongs_to :user, :foreign_key => :author_id

When I call the following:

feeds = Feed.includes(:user)

I want to skip over the default_scope for users. so I tried:

feeds = Feed.unscoped.includes(:user)

But this is not removing the scope from users. Any suggestions on how I can get this to work? Thank you

AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012
  • 1
    http://stackoverflow.com/questions/3963124/default-scope-and-associations or http://stackoverflow.com/questions/4758145/how-to-use-unscoped-on-associated-relations-in-rails3 help? – Nick Ginanto Jan 21 '13 at 19:40
  • 1
    Sadly, no. The first one is outdated. The 2nd one isn't detailing using includes. – AnApprentice Jan 21 '13 at 19:44

1 Answers1

17

You can accomplish this by using .unscoped in block form, as documented here:

User.unscoped do
  @feeds = Feed.includes(:user).all
end

Note that whether or not the default scope applies depends on whether or not you're inside the block when the query is actually executed. That's why the above uses .all, forcing the query to execute.

Thus, while the above works, this won't - the query is executed outside the .unscoped block and the default scope will apply:

User.unscoped do
  @feeds = Feed.includes(:user)
end
@feeds #included Users will have default scope
MrTheWalrus
  • 9,670
  • 2
  • 42
  • 66
  • 1
    Not sure I'm following, giving how I am querying for Feeds,and including :user for performance. How would this apply? – AnApprentice Jan 21 '13 at 20:05
  • 1
    @AnApprentice You asked how to avoid using the default scope on an association listed in `.includes`. This is how. You still eager load Users, but don't limit it to ones that aren't deleted. Isn't that what you wanted? – MrTheWalrus Jan 21 '13 at 20:07
  • Thanks, Yes but perhaps I'm not understanding the end to end to get this to work. Can you maybe share what I need to update and how to use it? – AnApprentice Jan 21 '13 at 20:08
  • 1
    Basically, you replace the `feeds = Feed.includes(:user)` with the block I provided wherever you use it, and it should solve the problem. (tested with Rails 3.2.2). Is that not happening? – MrTheWalrus Jan 21 '13 at 20:11
  • ok I needed to set it to @feeds so it was available outside. While it didn't error, it still is applying the scope to users: User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (1216, 1) AND (users.deleted_at IS NULL) – AnApprentice Jan 21 '13 at 20:16
  • 1
    A thought - the use or non-use of the default scope appears to depend on the point at which the relation actually gets executed and converted into an array. If you make sure that happens inside the block, it leaves off the default scope. If it doesn't, it doesn't. (going to edit answer to reflect this). – MrTheWalrus Jan 21 '13 at 20:23