LoginSignup
0
0

More than 5 years have passed since last update.

[Rails]モデルにScopeを定義し、コントローラーで呼び出す

Posted at

下記のように同じようなクエリメソッドを繰り返す場合、可読性も保守性も非常に悪いです。そんな時にはモデルにScopeを定義することで同じ記述を一つのメソッドとして使用することができます。

notes_controller.rb
    @manga_notes    = Note.where(category: 0).includes(:user).order("created_at DESC").limit(9)
    @column_notes   = Note.where(category: 1).includes(:user).order("created_at DESC").limit(9)
    @novel_notes    = Note.where(category: 2).includes(:user).order("created_at DESC").limit(9)
    @photo_notes    = Note.where(category: 3).includes(:user).order("created_at DESC").limit(9)
    @sound_notes    = Note.where(category: 4).includes(:user).order("created_at DESC").limit(9)
    @business_notes = Note.where(category: 5).includes(:user).order("created_at DESC").limit(9)

これらをScopeに定義することで一つのメソッドとして定義することができます。

note.rb
    scope :recent, -> { includes(:user).order("created_at DESC").limit(9) }
notes_controller.rb
    @manga_notes     = Note.where(category: 0).recent
    @column_notes    = Note.where(category: 1).recent

モデルで定義したScopeをコントローラーで呼び出しています。

note.rb
    enum category: { マンガ: 0, コラム: 1, 小説: 2, 写真: 3, サウンド: 4, ビジネス: 5, ライフスタイル: 6 }
    scope :search_with_category, ->(category) { where(category: category) }
    scope :recent, -> { includes(:user).order("created_at DESC").limit(9) }
notes_controller.rb
    @manga_notes     = Note.search_with_category(0).recent
    @column_notes    = Note.search_with_category(1).recent
    @novel_notes     = Note.search_with_category(2).recent
    @photo_notes     = Note.search_with_category(3).recent
    @sound_notes     = Note.search_with_category(4).recent
    @business_notes  = Note.search_with_category(5).recent
    @lifestyle_notes = Note.search_with_category(6).recent

上のようにスコープ同士をマージさせて使用することが可能です。また、スコープに引数を渡すことも可能で、上の例ではenumで定義しているカテゴリ番号を引数をして渡すことで、Noteモデルからそのカテゴリを持つレコードを取得します。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0