首页 > 解决方案 > 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_keyson #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错误或类似情况。

标签: ruby-on-railscancancancancan

解决方案


CanCan 文档规定了使用块定义能力的方法与您所做的方式略有不同。对于您描述的情况(当实例为零时),他们建议使用守卫而不是块:

# 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?

我会试试这个。有关其他信息并查看我从何处获得此示例,请查看这些文档


推荐阅读