【Rails】 default _scopeを解除する方法

rails エンジニア
記事内に広告が含まれています。

Railsのモデルにdefault_scopeを適用しているプロジェクトはあると思います。

そして、例外的にdefault_scopeを解除したいときもあるはずです。

そんなときは、「unscoped」「unscope」でdefault_scopeを解除することができます。

この記事ではその方法をご紹介します。

default_scopeとは

default_scopeを使うと、そのモデル全体に絞り込みやorderが適用されます。

下記の例ではArticleというモデルに対して、「published: true」なデータのみ取得します。

class Article < ActiveRecord::Base
  default_scope { where(published: true) }
end
Articleに「id:1, published: false」というデータがある場合はデータを取得しない、つまり空配列を返します。
> Article.where(id: 1)
SELECT "articles".* FROM "articles" WHERE "articles"."published" = 1 AND "articles"."id" = 1
=> #<ActiveRecord::Relation []>

default_scopeを解除する方法

unscoped (全てのクエリを解除)

unscopedを使用することで、default_scopeが解除されます。

> Article.unscoped.where(id: 1)
SELECT "articles".* FROM "articles" WHERE "articles"."id" = 1
=> #<ActiveRecord::Relation [#<Article id: 1, content: "test", published: false...>]>

しかし、一点注意することがあります。

それはupscopedを使用すると、default_scopeだけでなく、他のクエリも解除されてしまう点です。

下記のようにunscopedの前に付与したwhereも取り除かれてしまいます。

> Article.where(id: 1).unscoped
SELECT "articles".* FROM "articles

unscopedの後のクエリは適用されます。

> Article.unscoped.where(id: 1)
SELECT "articles".* FROM "articles" WHERE "articles"."id" = 1

そのため、unscopedを使用するタイミングは注意しましょう。

unscope (部分的にクエリを解除)

unscopeはunscopedと異なり、部分的にクエリを解除することができます。

> Article.unscope(where: :published)
SELECT "articles".* FROM "articles"
=> #<ActiveRecord::Relation [#<Article id: 1, content: "test", published: false...>]>
unscopeの前のクエリも適用されます。
> Article.where(id: 1).unscope(where: :published)
SELECT "articles".* FROM "articles" WHERE "articles"."id" = 1
=> #<ActiveRecord::Relation [#<Article id: 1, content: "test", published: false...>]>

コメント