CanCanCan 的方法仅在控制器或视图中可用,但我想在模型中访问它们,更具体地说是在模型的
save
方法中访问它们。我为此使用的解决方法如下:我在模型中创建一个 attr_accessor :ability
,并在调用保存之前在控制器中为其分配一个能力对象。
class Example
include ActiveModel::Model
attr_accessor :ability
def save
if ability.can?(:create, SomeOtherModel)
...
end
end
end
class ExamplesController < ApplicationController
def create
@example = Example.new(params[:example])
@example.ability = Ability.new(current_admin_user) #note: current_admin_user can be several separate models such as Admin, Support
if @example.save
...
end
end
end
是否有更好的方法从模型中调用
can?
?从安全角度或其他角度来看,此解决方案是否存在任何问题?
您还可以在模型中添加能力方法并委托 can?方法:
# app/models/user.rb
class User
delegate :can?, :cannot?, to: :ability
def ability
@ability ||= Ability.new(self)
end
end
some_user.can? :update, @article
https://github.com/CanCanCommunity/cancancan/blob/develop/docs/define_check_bility.md
使用这个解决方案,我认为您需要在所有需要检查能力的模型中定义
ability
方法,因此它可以有重复的代码。
从安全角度来看,这可能会导致意想不到的事情。控制器已经支持强大的参数来创建/更新模型允许的属性。
例如,如果支持人员只能更新某些属性,而管理员可以更新所有属性,那么您如何在模型中控制它?
如果您检查控制器中的能力,它可以阻止用户的操作并避免对服务器进行不必要的查询。
所以我认为为什么 CanCan 建议
can
方法在控制器和视图中效果最好
https://github.com/CanCanCommunity/cancancan/blob/develop/docs/controller_helpers.md