RailsのPundit::Scopeで一覧を絞り込む方法を完全解説!ロール・所有者別の認可を初心者向けに理解しよう
生徒
「Railsでログインしている人ごとに、見られる一覧を変えたいんですが、どうすればいいですか?」
先生
「Railsでは、Punditという認可ライブラリを使うと、安全に一覧データを絞り込めます。」
生徒
「一覧って、全部表示しちゃダメなんですか?」
先生
「ダメな場合が多いですね。Pundit::Scopeを使うと、ロールや所有者ごとに表示を制限できます。」
1. Railsの認可とは?Punditが必要な理由
Railsの認可とは、「この人がこのデータを見たり操作してもよいか」を判断する仕組みです。例えば、会員制サイトで、管理者だけが全データを見られて、一般ユーザーは自分のデータだけ見られる、という状況を想像してください。
Punditは、Railsでよく使われる認可ライブラリのひとつで、ポリシーというルール集を使ってアクセス制御を行います。特に一覧画面では、データを取得する時点で絞り込むことがとても重要です。
2. Pundit::Scopeとは何かを超やさしく説明
Pundit::Scopeは、「一覧で取得してよいデータの範囲」を決める仕組みです。たとえるなら、図書館で「この人はこの棚まで入っていい」という境界線を引く役割です。
コントローラでindexアクションを実行するとき、すべてのレコードをそのまま表示すると、見せてはいけない情報まで見えてしまうことがあります。そこでScopeを使い、最初から安全なデータだけを取得します。
3. Pundit::Scopeの基本構造
Punditでは、モデルごとにポリシークラスを作ります。その中にScopeクラスを定義します。まずは基本形を見てみましょう。
class ArticlePolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.all
end
end
end
scopeは、対象となるモデル(ここではArticle)を表します。resolveメソッドの戻り値が、一覧で表示されるデータになります。
4. 所有者別に一覧を絞り込む例
次に、「自分が作成したデータだけ見られる」ケースです。これは初心者が最初につまずきやすいポイントですが、とても大事です。
class ArticlePolicy < ApplicationPolicy
class Scope < Scope
def resolve
scope.where(user_id: user.id)
end
end
end
ここでのuserは、ログインしているユーザーを意味します。このように書くことで、「自分が所有している記事だけ」が一覧に表示されます。
5. ロール別(管理者・一般ユーザー)で制御する
次はロール別の制御です。ロールとは「役割」のことです。管理者は全部見られて、一般ユーザーは自分の分だけ、という形がよくあります。
class ArticlePolicy < ApplicationPolicy
class Scope < Scope
def resolve
if user.admin?
scope.all
else
scope.where(user_id: user.id)
end
end
end
end
admin?は、ユーザーが管理者かどうかを判定するメソッドです。条件分岐を使うことで、役割ごとに取得範囲を切り替えられます。
6. コントローラでPundit::Scopeを使う方法
ポリシーを書いただけでは動きません。コントローラでScopeを使ってデータを取得します。
class ArticlesController < ApplicationController
def index
@articles = policy_scope(Article)
end
end
policy_scopeを使うことで、Pundit::Scopeのresolveが自動的に呼ばれ、安全な一覧だけが取得されます。
7. なぜ一覧での認可が重要なのか
一覧画面は、ユーザーが最初に目にする場所です。ここで制御を間違えると、本来見えないはずの情報が簡単に漏れてしまいます。
Pundit::Scopeを使うと、データベースから取得する時点で絞り込めるため、あとから隠すよりも安全で効率的です。これはRailsのセキュリティを守るうえでとても重要な考え方です。
8. CanCanCanとの違いを簡単に理解
Railsの認可ライブラリには、PunditのほかにCanCanCanもあります。CanCanCanは「できる・できない」をルールとしてまとめるのが特徴です。
一方Punditは、モデル単位で考えるため、Railsの構造と相性がよく、Scopeで一覧を安全に制御しやすいというメリットがあります。初心者でも、責務が分かりやすいのが特徴です。