default_scope and associations

Viewed 9510

Suppose I have a Post model, and a Comment model. Using a common pattern, Post has_many Comments.

If Comment has a default_scope set:

default_scope where("deleted_at IS NULL")

How do I easily retrieve ALL comments on a post, regardless of scope? This produces invalid results:

Post.first.comments.unscoped

Which generates the following queries:

SELECT * FROM posts LIMIT 1;
SELECT * FROM comments;

Instead of:

SELECT * FROM posts LIMIT 1;
SELECT * FROM comments WHERE post_id = 1;

Running:

Post.first.comments

Produces:

SELECT * FROM posts LIMIT 1;
SELECT * FROM comments WHERE deleted_at IS NULL AND post_id = 1;

I understand the basic principle of unscoped removing all existing scopes, but shouldn't it be aware and to keep the association scope?

What is the best way to pull ALL comments?

6 Answers

with_exlusive_scope is deprecated as of Rails 3. See this commit.

Before (Rails 2):

Comment.with_exclusive_scope { Post.find(post_id).comments }

After (Rails 3):

Comment.unscoped { Post.find(post_id).comments }

How about this?

# Use this scope by default
scope :active, -> { where(deleted_at: nil) }

# Use this whenever you want to include all comments regardless of their `deleted_at` value
scope :with_soft_deleted, -> { unscope(where: :deleted_at)

default_scope, -> { active }

post.comments would fire this query:

SELECT "comments".* FROM "comments" WHERE "comments"."deleted_at" IS NULL AND "comments"."post_id" = $1;

post.comments.with_soft_deleted would send this:

SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1;
Related