ActiveRecord で unscoped を呼ぶとその前のクエリが消える

久々ですこんにちは。
毎日ブログを書くとはなんだったのか…。
そろそろアウトプットしたいな〜〜〜と思い始めてきたのでぼちぼち書いていきたい…。

unscoped を使うことで default_scope を取り除くことができる

さて、皆さん大好き default_scope ですが、モデルで default_scope を定義すると次のように暗黙的にクエリが追加されます。

class User < ActiveRecord::Base
  default_scope { order(:updated_at) }
end

# 暗黙的に ORDER BY のクエリが追加れる
puts User.all.to_sql
# => SELECT "users".* FROM "users" ORDER BY "users"."updated_at" ASC
puts User.where(name: "Tom").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."name" = 'Tom' ORDER BY "users"."updated_at" ASC

毎回 order(:updated_at) する必要がないので便利ですね。
でも『あ〜今日は default_scope のクエリ追加してほしくないな〜〜〜』って思うときがあると思うんですよ。
そういう時に unscoped を使うと default_scope のクエリを取り除く事ができます。

# unscoped を付けると default_scope はつかなくなる
puts User.unscoped.all.to_sql
# => SELECT "users".* FROM "users"
puts User.unscoped.where(name: "Tom").to_sql
# => SELECT "users".* FROM "users" WHERE "users"."name" = 'Tom'

これで default_scope をつかっていてもシュッと取り除く事ができて便利ですね!

default_scope 以外のクエリも取り除かれる

unscoped を使うことで default_scope を取り除く事ができるようになります。
しかし unscoped はめちゃくちゃ強くて『呼び出すよりも前のリレーション』も取り除いてしまします。

# unscoped よりも前に付けた where のクエリも消してしまう
puts User.where(name: "Tom").unscoped.to_sql
# => SELECT "users".* FROM "users"

unscopeddefault_scope を消したい場合は必ず『一番最初』に unscoped を呼び出しましょう。
逆に『レシーバのクエリを全部消したい』場合は unscoped を呼び出すと一括で消すことができるので便利です。