CanCanCan:如何处理在Ability模型中为零的对象?

时间:2019-09-10 14:39:47

标签: ruby-on-rails cancan cancancan

我有这个控制器:

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操作)时,@usernil。因此无法设置该角色,因为该角色不会添加到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错误或类似错误。

2 个答案:

答案 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