我有这个控制器:
class UsersController < ApplicationController
load_and_authorize_resource
def create
@user.save
respond_with @user
end
def update
@user.update user_params
respond_with @user
end
def destroy
@user.destroy
respond_with @user
end
private
def user_params
permitted_keys = [:name,
:email,
:password,
:password_confirmation,
:lock_version]
permitted_keys << :role if can? :edit_role, @user
params.require(:user).permit(permitted_keys)
end
end
在我的能力模型中:
can :edit_role, User do |user|
user.new_record?
end
问题是,当创建用户(#new
或#create
操作)时,@user
是nil
。因此无法设置该角色,因为该角色不会添加到permitted_keys
上的#create
上。
如何解决?我可以将控制器更改为:
permitted_keys << :role if action_name == 'create'
但是我不喜欢这样,因为Ability
比这更容易测试。
另一个解决方法是:
permitted_keys << :role if can? :edit_role, @user || User.new
但这感觉很多余。
有人有更好的主意吗?顺便说一下-我很惊讶将nil
作为对象传递给can?
是允许的,并且不会引发错误。似乎它甚至没有传播到Ability
中的实际配置,否则user.new_record?
会引发NoMethod
错误或类似错误。
答案 0 :(得分:1)
CanCan文档规定了使用块定义能力的方式与您的完成方式有所不同。他们建议针对您所描述的情况(当实例为nil时)使用防护而不是块:
# don't do this
can :edit_role, User do |user|
user.new_record? # this won't be called for User.accessible_by(current_ability, :edit_role)
end
# do this
can :edit_role, User if user.new_record?
我会尝试的。有关其他信息,以及我在哪里获得此示例,请check these docs
答案 1 :(得分:0)
似乎使用CanCanCan gem,在创建{
"files": [
{
"pattern": "barbarian/CSS/2.12.8-1+gccb456e/PR-495/0/package/"
},
{
"pattern": "barbarian/BS/2.12.8-1+gccb456e/PR-495/0/package/"
}
]}
变量之前调用了user_params
方法;之所以这样,是因为创建@user
变量需要user_params
,或者至少需要从表单中分配值。
如果CanCanCan在分配表单中的值之前要分配一个新的@user
变量(当然是@user
类型),则以下代码将在User
上起作用:
#create
但是由于它显然没有做到这一点,因此以下变通办法对我有效:
private
def user_params
permitted_keys = [:name,
:email,
:password,
:password_confirmation]
permitted_keys << :role if can? :edit_role, @user
permitted_keys << :disabled if can? :disable_user, @user
params.require(:user).permit permitted_keys
end