🍙

【Rails/CanCanCan】関連付けを利用したload_resource

2024/12/27に公開

はじめに

CanCanCan は Ruby on Railsの認可ライブラリで、特定のユーザーがアクセスできるリソースを制限できる機能があります。
https://github.com/CanCanCommunity/cancancan

今回は、コントローラで関連付けを利用してリソース読み込みを行うload_resourcethroughオプションについて紹介します。

使い方

コントローラで以下のように記述すると、authorリソースを通じたリソースの読み込みが行われ、アクションに応じて@books@bookがセットされます。(コントローラにインスタンス変数@authorやメソッドauthorの定義が必要)

class BooksController < ApplicationController
  load_resource through: :author
end

リソース読み込みの流れ

実際にLibraryの該当箇所のコードを見ていきます。

処理は大きく分けて以下の2段階に分かれます

  • 親リソースの取得
  • 子リソースの読み込み

親リソースの取得

https://github.com/CanCanCommunity/cancancan/blob/c63cde14d419474a9da2ddb03956440045348577/lib/cancan/controller_resource_loader.rb#L50-L61

親リソースの名前parent_nameをもとに、コントローラのインスタンス変数を確認し、存在しない場合は同名のメソッド呼び出しを行います。

子リソースの読み込み

https://github.com/CanCanCommunity/cancancan/blob/c63cde14d419474a9da2ddb03956440045348577/lib/cancan/controller_resource_loader.rb#L106-L112

今回は、show, edit, destroyアクションの場合を考えていきます。
load_resource_instanceの中でfind_resourceが呼び出されます。

https://github.com/CanCanCommunity/cancancan/blob/c63cde14d419474a9da2ddb03956440045348577/lib/cancan/controller_resource_finder.rb#L7-L15

singletonfind_byオプションを設定しない、三つ目の条件分岐を通る場合を考えます。

今回の設定ではresource_baseの部分で以下が行われます

  • 前述のparent_resourceにより親リソース@authorの取得が行われる
  • sendメソッドにより、@authorに対してコントローラ名の複数形booksメソッドを呼び出す

これにより、@author.books の結果から、id_param で指定された ID に一致するリソースを検索する処理が行われます。

まとめ

  • コントローラーでload_resource through: :<インスタンス変数名>/<メソッド名> と記述することで、関連付けを利用したリソース読み込みが可能

Discussion