Help us understand the problem. What is going on with this article?

Railsでよく利用する、Scopeの使い方。

Scope(スコープ)とは

scopeとは、クラスメソッドを使う際、可読性を保つためにあるものです。

例えば、あるUserのidを降順にし、かつ5つだけ表示させたい場合、以下のようなメソッドを使うことになります。

  User.order(id: desc).limit(5)

しかし、このような記述をもしいろんなところで使うとした場合、長ったらしいメソッドチェーンを書くのは面倒だし、コントローラ側で使うときに可読性が落ちます。

そういったときに使うのがscope。
上と同じ式を一つのメソッドとして定義できます(ここでいうrecent)

user.rb
class User < ApplicationRecord
  scope :recent, -> { order(id: :desc).limit(5) }
end
users/controller.rb
class UsersController < ApplicationController

def index
  @users = User.recent
end

これでコントローラ側でもUser.recentを使えるようになり、より簡潔になりましたね。

また、スコープに引数を渡すことも可能です。

user.rb
class User < ApplicationRecord
  scope :recent, -> (count) { order(id: :desc).limit(count) }
end
users/controller.rb
class UsersController < ApplicationController

def index
  @users = User.recent(10)
end

これで、コントローラ側でUser.recent(10)を呼べば最新の10件が取得できるようになります。

スコープは簡潔に、使いやすく

Modelを呼ぶ際、どこからでも使えて便利なスコープですが、そのどこからでも使えるという部分において考慮すべき点があります。
それは、scope側をシンプルに記述してあげるという点です。

というのも、コントローラによってscopeに渡す値も違うからです。

例えば、国別でUserを検索する以下のスコープがあるとします。

scope :serch_user, ->(country) do
  return if country.nil? 
  country == "japan" ? where(country: true) : where(country: false)
end
scope :serch_user, ->(country) do
  return if country.nil? 
  country ? where(country: true) : where(country: false)
end

前者はcountryが"japan"という文字列で条件分岐しているのに対し、後者はcountryがtrueかfalseかによって分岐させています。
この場合、どう考えても単にbooleanで分岐させている後者のスコープの方が使い安いですよね。
前者の場合、わざわざ"japan"という文字でスコープに渡さなければなりません。

まとめ

僕はscopeを作る際、以下のように考えてました。
viewから値を取ってくる → コントローラに渡す → そのままscopeに渡す

しかし、この発想ではそのコントローラでしか扱えないようなscopeになってしまう恐れがあります。 なので、
viewから値を取ってくる → コントローラに渡す → コントローラ側で、scopeで使える形に変換 →  scopeに渡す
という前提でscopeを作る必要があります。
なので、scopeはどのコントローラからでも使いやすく、単純なものにする必要があるのです。
(と、多分いろいろ間違えてるのでご指摘ありましたらよろしくお願いしますm( )m)

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away