ActiveModelのscopeを✅
PF進捗会に参加して、酒ケジュール作成のヒントをもらった。スコープを活用して条件を決めておくことで、提供したいお酒のアルコール度数をグルーピングできるようで。
「お酒の強さがweakだったユーザーの場合はpercentageが0〜7のお酒、strongだったユーザーの場合はpercentageが8以上のお酒」が提供される流れを実装したい。
なので、今回はRailsのscope機能を学習していきたい。
scopeとは
スコープを設定することで、関連オブジェクトやモデルへのメソッド呼び出しとして参照される、よく使用されるクエリを指定することができます。スコープでは、
where
、joins
、includes
など、これまでに登場したすべてのメソッドを使用できます。どのスコープメソッドも、常にActiveRecord::Relation
オブジェクトを返します。このオブジェクトに対して、別のスコープを含む他のメソッド呼び出しを行なうこともできます。
テーブルを関連づけたり、昇順降順で並べ替えるエイリアスを作成することができる。
どう使うのか
下記のように、scopeの後に、エイリアスを用意する。
class Analyze < ApplicationRecord
...
# deletedカラムがfalseであるものを取得する
scope :active, -> { where(deleted: false) }
# created_atカラムを降順で取得する
scope :sorted, -> { order(created_at: :desc) }
# activeとsortedを合わせたもの
scope :recent, -> { active.sorted }
...
end
scopeはコントローラーで呼び出すことができる。
class AnalyzesController < ApplicationController
def index
@analyzes = Analyze.all.sorted
render json: @analyzes
end
end
単一責務を持ったscopeを用意することで、再利用性が高まる。
なので、下記のように一気にまとめるのではなく、active,sortedのように分けている。
class AnalyzesController < ApplicationController
def index
@analyzes = Analyze.all.where(deleted: false).order(created_at: :desc)
render json: @analyzes
end
end
実際に発行されるSQL
実際にポートフォリオに使ってみる
まずは実現したい挙動を言葉にまとめてみる。
「度数が7%未満のお酒をランダムで4件取得する」と「度数が7%超のお酒をランダムで4件取得する」
class Alcohol < ApplicationRecord
scope :random_weak, ->{ self.where('alcohol_percentage < ?', 7).shuffle[0..4] }
scope :random_strong, ->{ self.where('alcohol_percentage > ?', 7).shuffle[0..4] }
end
発行されるSQL文
まとめ
- コントローラーにSQL文を記述する時に、肥大化しそうな匂いがしたらモデルに切り出す。
- お酒って面白い。