Railsのdefault_scopeは使うな、絶対(翻訳)

概要

原著者の許諾を得て翻訳・公開いたします。

Railsのdefault_scopeは使うな、絶対(翻訳)

あるモデル全体にスコープを適用したい場合、default_scopeが利用できます。詳しくはRailsガイド: Active Recordクエリインターフェイス 14.スコープ(日本語)かRailsドキュメントをご覧ください。


投稿を非表示にできる機能を持つブログシステムを書き始めるときを考えてみます。

次のように書かないこと

default_scopeを使う:

# app/models/post.rb
class Post < ActiveRecord::Base
  default_scope { where(hidden: false) }
end

次のように書くこと

明示的にスコープを指定する:

# app/models/post.rb
class Post < ActiveRecord::Base
  scope, :published -> { where(hidden: false) }
end

これで次のように書けます。

Post.published

なぜdefault_scopeがだめなのか

理由は2つあります。どちらも後になってコードが混乱したりバグつぶしに明け暮れたりすることを避けるのが目的です。

default_scopeを追加すると、モデルの初期化が影響を受けます。上の例で言うと、開発者が期待するかどうかにかかわらずPost.newするとデフォルトでhidden = falseになってしまいます。

いったん定義されたdefault_scopeを使わないようにするのは大変です。default_scopeが不要な場面で削除するには、unscopedしたスコープ(!)を使わなければならず、しかも適用されていた関連付けなどの条件はすべて削除されてしまいます。

: Post.first.comments.unscopedとすると、Postの最初のコメントだけではなく、データベース内のすべてのコメントを返します。

default_scopeより明確な解決法は、明示的な名前付きスコープを使うことです。default_scopeを使えばバグつぶしに何時間も費やすことになるでしょう。default_scopeは使わないでください。

default_scopeを使ってもよさそうな場面はありますか?

どうかこればかりは私を信じてください。使えばきっと痛い目にあいます。

関連記事

よくある?Rails失敗談 default_scope編

論理削除用paranoia gemがあるRailsプロジェクトで物理削除する方法

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833 コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。 これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 実は最近Go言語が好き。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ