cancancan中load_resource的用法小结。
正文:
最基本的用法:
class TasksController < ApplicationController
load_resource
end
#### 等同于 @task = Task.find(params[:id]), @task = Task.new, @tasks = Task.all
options 众多,来一一捋捋。【借鉴cancancan的wiki,以下代码多以 task,project 为例。】
only / except
同before_action中的only / except,指明load_resource在哪些action前调用。
only:
class TasksController < ApplicationController load_resource only: [:index, :show] end ### 仅在 index,show action 前调用load_resource
except:
class TasksController < ApplicationController load_resource except: [:sent] end ### 在除 sent action 外的其他actions前调用load_resource
through
通过A,B之间的关联来load某一方。
class Project < ActiveRecord has_many :tasks end class TasksController < ApplicationController load_resource :project load_resource :task, through: :project ## 这里也可以省略 :task end #### 等同于: @project = Project.find(params[:project_id]) #### @task = @project.tasks.find(params[:id])
也可以通过method,比如:current_user,也就是wiki中所说的nested through method:
class TasksController < ApplicationController load_resource through: :current_user end #### 等同于: @task = current_user.tasks.find(params[:id])
through_association
与through的不同在于,project中,如果给tasks起了“别名”,不是,
has_many tasks
, 而是长这样:class Project < ActiveRecord has_many :events, class_name: 'Task' end
则在taskController中需要通过through_association来指明:
class TasksController < ApplicationController load_resource :project load_resource :task, through: :project, through_association: :events end #### 等同于:@project = Project.find(params[:project_id]), #### @task = @project.events.find(params[:id])
shallow
shallow是跟着through的,设置为true则允许parent resource为 nil,设置为false则不允许nil,默认为false。
class TasksController < ApplicationController load_resource :project load_resource :task, through: :project, shallow: true end #### 等同于: #### @project存在,则@task = @project.events.find(params[:id]) #### @project不存在,则@task = Task.find(params[:id])
singleton
当project与task存在一对一关系:
class Project < ActiveRecord has_one :task end class TasksController < ApplicationController load_resource :project load_resource :task, through: :project, singleton: true end #### 等同于: @project = Project.find(params[:project_id]) #### @task = @project.task
parent
根据这个resource是不是一个parent resource来决定,当resource的name与controller无法匹配时,则默认为是parent resource。比如:
class TasksController < ApplicationController load_resource :project load_resource :task, through: :project end
这里,project在task的controller中,就是一个parent resource。
class
指定类名。多用于当controller与model无法匹配时。
常见的是个人中心这样的ProfilesController,对应的类名是User:
class ProfilesController < ApplicationController load_resource :profile, class: User end #### 等同于: @profile = User.find(params[:id])
find_by
指定find_by_[attribute]。比如:
class PersonationsController < ApplicationController load_resource find_by: :token, class: User end #### 等同于: @personation = User.find_by_token(params[:id])
注意,此处是params[:id], 不是params[:token],如果需要设置params fetch的attribute,可以用id_params.
Id_params
默认是id,可以改为其他的param key,比如上面的例子:
class PersonationsController < ApplicationController load_resource find_by: :token,, class: User, id_params: :token end #### 等同于: @personation = User.find_by_token(params[:token])
可以将through,find_by, id_params 结合运用:
以常见的一个订阅为例, 用户订阅项目:
class SubscriptionsController < ApplicationController before_action { @user = current_user } load_resource through: :user, find_by: :project_id, id_param: :project_id end #### 等同于: #### @subscription = @user.subscriptions.find_by_project_id(params[:project_id])
new
指定除默认的new,create之外,哪些action需要new resource。
class TasksController < ApplicationController load_resource new: :build def build ..... end end #### 等同于: 在调用build action前,执行 @task = Task.new
prepend
值为true或者false,默认false。如果设置为true,则会调用prepend_before_filter 而不是 before_filter。