代码之家  ›  专栏  ›  技术社区  ›  Joshua Muheim

坎坎坎:如何处理能力模型中为零的对象?

  •  0
  • Joshua Muheim  · 技术社区  · 5 年前

    我有这个控制器:

    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 #创建 .

    这怎么解决?我可以将控制器更改为:

    permitted_keys << :role if action_name == 'create'
    

    但我不喜欢这样 Ability 比这更容易测试。

    另一个解决方法是:

    permitted_keys << :role if can? :edit_role, @user || User.new
    

    但这感觉是多余的。

    有人有更好的主意吗?顺便说一下-我很惊讶 作为对象 can? 允许且不会引发错误。似乎它甚至没有传播到 能力 ,否则 user.new_record? 会引起 NoMethod 错误或类似的。

    0 回复  |  直到 5 年前
        1
  •  1
  •   yez    5 年前

    坎坎医生用方块来定义能力的方法和你做的有点不同。他们建议在您描述的情况下(当实例为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

        2
  •  0
  •   Joshua Muheim    5 年前

    似乎用 CanCanCan 宝石 user_params 方法在 @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
    end