Railsのdefault_scopeは使うな、絶対(翻訳)
あるモデル全体にスコープを適用したい場合、default_scope
が利用できます。詳しくはRailsガイド: Active Recordクエリインターフェイス 14.スコープ(日本語)かRails APIドキュメントをご覧ください。
投稿を非表示にできる機能を持つブログシステムを書き始めるときを考えてみます。
次のように書かないこと
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
を使ってもよさそうな場面はありますか?
どうかこればかりは私を信じてください。使えばきっと痛い目にあいます。
概要
原著者の許諾を得て翻訳・公開いたします。