【问题标题】:CanCan load_and_authorize_resource triggers Forbidden AttributesCanCan load_and_authorize_resource 触发 Forbidden Attributes
【发布时间】:2012-10-06 03:34:05
【问题描述】:

我有一个使用强参数的标准 RESTful 控制器。

class UsersController < ApplicationController
  respond_to :html, :js

  def index
    @users = User.all
  end

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def edit
    @user = User.find(params[:id])
  end

  def create
    @user = User.new(safe_params)

    if @user.save
      redirect_to @user, notice: t('users.controller.create.success')
    else
      render :new
    end
  end

  def update
    @user = User.find(params[:id])

    if @user.update_attributes(safe_params)
      redirect_to @user, notice: t('users.controller.update.success')
    else
      render :edit
    end
  end

  def destroy
    @user = User.find(params[:id])

    if current_user != @user
      @user.destroy
    else
      flash[:error] = t('users.controller.destroy.prevent_self_destroy')
    end
    redirect_to users_url
  end

  private

  def safe_params
    safe_attributes =
      [
        :first_name,
        :last_name,
        :email,
        :password,
        :password_confirmation,
      ]
    if current_user.is?(:admin)
      safe_attributes += [:role_ids]
    end
    params.require(:user).permit(*safe_attributes)
  end
end

在我的config/initializers 我有文件strong_parameters.rb

ActiveRecord::Base.send(:include,  ActiveModel::ForbiddenAttributesProtection)

当我向 CanCan 的 load_and_authorize_resource 添加一个简单的调用时,我得到了

1) UsersController POST create with invalid params re-renders the 'new' template
 Failure/Error: post :create, user: @attr
 ActiveModel::ForbiddenAttributes:
   ActiveModel::ForbiddenAttributes
 # ./spec/controllers/users_controller_spec.rb:128:in `block (4 levels) in <top (required)>'

其中@attr在测试中定义为

  before(:each) do
    @attr =
      {
        first_name: "John",
        last_name: "Doe",
        email: "user@example.com",
        password: "foobar",
        password_confirmation: "foobar"
      }
  end

在测试中,我已正确设置所有内容以登录用户并为他们提供成为管理员所需的角色,所以我知道并非如此。我不知道为什么这会导致 ForbiddenAttributes 触发。我敢肯定这是我忽略的一些简单的事情。有没有其他人遇到过这个问题并找到了解决方案?

【问题讨论】:

    标签: ruby-on-rails ruby rspec2 cancan strong-parameters


    【解决方案1】:

    我相信这是因为如果你不使用 before_filter 预加载 CanCan 将使用它自己的 getter 方法获取请求的资源。所以你可以将它添加到控制器中,它应该可以工作:

    class UsersController < ApplicationController
      before_filter :new_user, :only => [:new, :create]
    
      load_and_authorize_resource
    
      def new_user
        @user = User.new(safe_params)
      end
    end
    

    (然后对编辑/更新操作执行相同操作。)

    【讨论】:

    • 我相信我遇到了同样的问题。您介意进一步澄清您的解决方案吗?
    • 已经有一段时间了,但我会试一试;) 哪一部分给您带来了麻烦?基本上,如果您调用cancan 的load_and_authorize_resource,它将尝试加载给定控制器名称的最“合乎逻辑”的资源,该名称在强参数gem 的操作之前。在这种情况下,它将尝试构建用户 @user = User.new(params[:user]) 但 strong_parameters 不允许以这种方式进行批量分配。如果您使用before_filter 设置@user 实例变量,CanCan 将只使用它。如果您的 before_filter 符合 strong_parameters 它不应该引发错误。
    • 啊非常感谢!我不明白 CanCan 是如何“......[使用]它自己的 getter 方法......”但现在这很有意义。再次感谢!
    • 很高兴我能帮上忙!祝你的项目好运!
    • @PeterDuijnstee:我相信你想要 :only => [:create],而不是 :only => [:new, :create]。 :new 根本没有任何参数。因此,它会阻塞 params.require(:user).permit(*safe_attributes) 上的 safe_params
    【解决方案2】:
    before_filter do
      params[:user] = safe_params
    end
    load_and_authorize_resource
    

    【讨论】:

    • 这里主要强调 before_filterload_and_authorize_resource 之前
    猜你喜欢
    • 2015-08-30
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多