目的
scope基本的なことをとりあえずメモ程度でもいいので残して置くために書きました。
[WIP]scopeはよく使うので、今後scopeの様々な使い方を紹介していきます。
目次
- scopeとは
- scopeの利用例
- default_scopeについて(使ったことないけど情報だけ)
1. scopeとは
共通的に使うクエリをモデルのメソッドのように定義できるやつです。
複雑なSQLを何度も書かなくていいし、保守性に優れて、レビュアーにとっても読みやすくなるので良い関係を築けるかもです。
後、同じことがcontrollerでもできるのですが『Skinny Controller, Fat Model(コントローラーのコード量を少なくして、モデルを分厚くする)』という書き方が推奨されています。
このような背景から、ファットモデルという設計が目指すべき設計ということになります。
2. scopeの利用例(基本形だけ)
class Article < ApplicationRecord
enum state: %i[draft published]
scope :viewable, -> { published.where('published_at < ?', Time.current) }
=begin
:viewable <-メソッド名
published <- enumで定義したやつ。articlesテーブルでステータス「公開」のやつ
.where('published_at < ?', Time.current) }
「.where」は条件定義するメソッド。
('published_at < ?', Time.current) }は「公開日が現在時刻より前」
まてめ->ステータス「公開」で「公開日が現在日時より前」のデータを取得してこいというメソッド
豆知識「Time.nowとTime.currentの違い」
Time.now -> システムのタイムゾーンになる(Ruby組み込みのメソッド)
Time.current -> config.time_zoneで設定したタイムゾーンになる(Rails独自のメソッド)
=end
end
3. default_scopeについて(使ったことないけど情報だけ)
モデルで共通で適用される scope を定義するために、default_scopeという機能があります。
一見便利な印象を受けるのですが、影響範囲が大きすぎるため、意図しない挙動を生む場合があります。
そのため、default_scope は安易に利用しないほうがいいっぽいです。
🔥なぜdefault_scopeがだめなのか
Railsのdefault_scopeは使うな、絶対(翻訳)を参考
理由は2つあります。どちらも後になってコードが混乱したりバグつぶしに明け暮れたりすることを避けるのが目的です。
default_scopeを追加すると、モデルの初期化が影響を受けます。
いったん定義されたdefault_scopeを使わないようにするのは大変です。
default_scopeが不要な場面で削除するには、unscopedしたスコープ(!)を使わなければならず、
しかも適用されていた関連付けなどの条件はすべて削除されてしまいます。
例: Post.first.comments.unscopedとすると、Postの最初のコメントだけではなく、データベース内のすべてのコメントを返します。
default_scopeより明確な解決法は、明示的な名前付きスコープを使うことです。
default_scopeを使えばバグつぶしに何時間も費やすことになるでしょう。default_scopeは使わないでください。
## 参考