カテゴリー:
Rails
タグ:
 Rails unscoped default_scope

このエントリーをはてなブックマークに追加
更新日時:
2014年04月21日(月)
作成日時:
2014年04月21日(月)

前の記事 / 次の記事

結論

  • default_scope は本当にdefaultの 時だけ使おう
  • unscoped する時には素直にモデルクラスから使おう

と思った。
以下そう思った理由。

基本

Railsにはdefault_scopeていう機能があって、
default_scopeするとデフォルトでそのスコープのレコードを取得してくれる。

class Article < ActiveRecord::Base
  default_scope -> { where published: true }
end

これで、

@articles = Article.all

とかするとpublishedなarticlesを取得することができる。
で、一時的にdefault_scopeを外したい時は、unscopedという機能を使って

@articles = Article.unscoped.all

とすればpublishedじゃないarticleも含めたarticlesを取得することができる。

ちょっと頑張ろうとすると

単純な使い方であるならこれで問題ないのだけど、

@user = User.find(user_id)
@articles = user.articles

とかしたい場合、まず特に何も書かなければdefault_scopeが適用されて、
publishedなarticlesだけが取得される。

publishedじゃないarticleも含めて取得したい場合は、

@user = User.find(user_id)
@articles = user.articles.unscoped

と書いたら行けそうな気分になるんだけど、
実際はuserとの関連も含めた全てのスコープが外れるのでこの記述だと

Articles.unscoped.all

と同じになる。

んー、微妙。

微妙と思ったら自分が微妙

Railsにおいて本当に微妙な機能っていうのはどんどん非推奨になっていくので
この機能が生き残ってるということはおそらく自分の方が微妙なんだろうと思いました。

Railsのリファレンスを見ると、
unscopedはスコープのメソッドチェーンとしてではなくシンプルにモデルクラスから呼ばれています。

つまりそもそもそういう風に使えと、Rails神は言っているのだと思います。

モデルクラスからシンプルに呼ばれることを想定して書かれたメソッドであって、
スコープのメソッドチェーンとして使うこととか想定してねーからと。

結論のような何か

そもそもdefault_scopeなんだからそれを外そうとかいう発想が頭おかしくて、
どうしても外したい場合は例外的にモデルクラスからunscoped使って呼んでね、
例外だから別にメソッドチェーンできなくてもいいよね?
っていうことなんだろうと、

思いました。