我有这个控制器:
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。因此无法设置该角色,因为它不会添加到#create上的permitted_keys。
如何解决这个问题呢?我可以将我的控制器更改为:
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错误或类似的错误。
发布于 2019-09-12 01:06:52
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
发布于 2019-09-25 16:12:28
似乎使用CanCanCan gem时,user_params方法是在创建@user变量之前调用的;这种方法很有意义,因为需要user_params来创建@user变量,或者至少需要它来从表单赋值。
如果CanCanCan在从表单赋值之前分配一个新的@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但由于它显然不能做到这一点,下面的变通方法适用于我:
private
def user_params
permitted_keys = [:name,
:email,
:password,
:password_confirmation]
auth_object = @user || User.new
permitted_keys << :role if can? :edit_role, auth_object
permitted_keys << :disabled if can? :disable_user, auth_object
params.require(:user).permit permitted_keys
endhttps://stackoverflow.com/questions/57873176
复制相似问题