cancancan中load_resource的用法小结。
正文:
最基本的用法:
1 | class TasksController < ApplicationController |
options 众多,来一一捋捋。【借鉴cancancan的wiki,以下代码多以 task,project 为例。】
only / except
同before_action中的only / except,指明load_resource在哪些action前调用。
only:
1
2
3
4
5class TasksController < ApplicationController
load_resource only: [:index, :show]
end
### 仅在 index,show action 前调用load_resourceexcept:
1
2
3
4
5class TasksController < ApplicationController
load_resource except: [:sent]
end
### 在除 sent action 外的其他actions前调用load_resourcethrough
通过A,B之间的关联来load某一方。
1
2
3
4
5
6
7
8
9
10
11class 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:
1
2
3
4
5class TasksController < ApplicationController
load_resource through: :current_user
end
#### 等同于: @task = current_user.tasks.find(params[:id])through_association
与through的不同在于,project中,如果给tasks起了“别名”,不是,
has_many tasks
, 而是长这样:1
2
3class Project < ActiveRecord
has_many :events, class_name: 'Task'
end则在taskController中需要通过through_association来指明:
1
2
3
4
5
6
7class 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。
1
2
3
4
5
6
7
8class 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存在一对一关系:
1
2
3
4
5
6
7
8
9
10
11class 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.taskparent
根据这个resource是不是一个parent resource来决定,当resource的name与controller无法匹配时,则默认为是parent resource。比如:
1
2
3
4class TasksController < ApplicationController
load_resource :project
load_resource :task, through: :project
end这里,project在task的controller中,就是一个parent resource。
class
指定类名。多用于当controller与model无法匹配时。
常见的是个人中心这样的ProfilesController,对应的类名是User:
1
2
3
4
5class ProfilesController < ApplicationController
load_resource :profile, class: User
end
#### 等同于: @profile = User.find(params[:id])find_by
指定find_by_[attribute]。比如:
1
2
3
4
5class 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,比如上面的例子:
1
2
3
4
5class 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 结合运用:
以常见的一个订阅为例, 用户订阅项目:
1
2
3
4
5
6
7class 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。
1
2
3
4
5
6
7
8
9class TasksController < ApplicationController
load_resource new: :build
def build
.....
end
end
#### 等同于: 在调用build action前,执行 @task = Task.newprepend
值为true或者false,默认false。如果设置为true,则会调用prepend_before_filter 而不是 before_filter。