首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CanCanCan:如何处理能力模型中为空的对象?

CanCanCan:如何处理能力模型中为空的对象?
EN

Stack Overflow用户
提问于 2019-09-10 22:39:48
回答 2查看 190关注 0票数 1

我有这个控制器:

代码语言:javascript
运行
复制
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

在我的能力模型中:

代码语言:javascript
运行
复制
    can :edit_role, User do |user|
      user.new_record?
    end

问题是,在创建用户(#new#create操作)时,@usernil。因此无法设置该角色,因为它不会添加到#create上的permitted_keys

如何解决这个问题呢?我可以将我的控制器更改为:

代码语言:javascript
运行
复制
permitted_keys << :role if action_name == 'create'

但我不喜欢这样,因为Ability可以比这更容易测试。

另一种解决方法是:

代码语言:javascript
运行
复制
permitted_keys << :role if can? :edit_role, @user || User.new

但这感觉是多余的。

谁有更好的主意?顺便说一句,我很惊讶,将nil作为对象传递给can?是允许的,而且不会引发错误。它似乎甚至不会传播到Ability中的实际配置,否则user.new_record?将引发NoMethod错误或类似的错误。

EN

回答 2

Stack Overflow用户

发布于 2019-09-12 01:06:52

CanCan文档规定用块来定义异能的方式与你所做的略有不同。他们建议在您描述的情况下使用防护而不是块(当实例为nil时):

代码语言:javascript
运行
复制
# 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
EN

Stack Overflow用户

发布于 2019-09-25 16:12:28

似乎使用CanCanCan gem时,user_params方法是在创建@user变量之前调用的;这种方法很有意义,因为需要user_params来创建@user变量,或者至少需要它来从表单赋值。

如果CanCanCan在从表单赋值之前分配一个新的@user变量(当然是User类型),下面的代码将在#create上工作

代码语言:javascript
运行
复制
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

但由于它显然不能做到这一点,下面的变通方法适用于我:

代码语言:javascript
运行
复制
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
end
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57873176

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档