December 29, 2020
This blog is part of our Rails 6.1 series.
Before Rails 6.1 if a default_scope was defined in a model it would be applied
only for select and insert queries. Rails 6.1 adds an option
all_queries: true that could be passed to default_scope to make the scope
applicable for all queries.
default_scope -> { where(...) }, all_queries: true
Consider the Article class below.
class Article
default_scope -> { where(organization_id: Current.organization_id) }
end
@article.update title: "Hello World"
@article.delete
The update and delete methods would generate SQL queries as shown below. As
we can see that default_scope is missing from these queries.
UPDATE "articles" SET "title" = $1 WHERE "articles"."id" = $2 [["title", "Hello World"], ["id", 146]]
DELETE FROM "articles" WHERE "articles"."id" = $1 [["id", 146]]
In Rails 6.1 we can solve this problem by passing all_queries: true to the
default_scope.
class Article
default_scope -> { where(organization_id: Current.organization_id) }, all_queries: true
end
Then the generated SQL changes to this:
UPDATE "articles" SET "title" = $1 WHERE "articles"."id" = $2 AND "articles"."organization_id" = $3 [["title", "Hello World"], ["id", 146], ["organization_id", 314]]
DELETE FROM "articles" WHERE "articles"."id" = $1 AND "articles"."organization_id" = $2 [["id", 146], ["organization_id", 314]]
Ability to make default_scopes applicable to all queries is particularly useful
in the case of multi-tenanted applications, where an organization_id or
repository_id is added to the tables to support sharding.
Check out the pull request for more details on this feature.
Follow @bigbinary on X. Check out our full blog archive.