42

随着最近升级到 Rails 4,使用类似于下面的代码更新属性不起作用,我收到一个ActiveModel::ForbiddenAttributes错误:

@user.update_attributes(params[:user], :as => :admin)

User 在模型中有以下 attr_accessible 行:

attr_accessible :role_ids, :as =>admin
# or any attribute other than :role_ids contained within :user

你如何在 Rails 4 中完成同样的任务?

4

5 回答 5

42

Rails 4 now has features from the strong_parameters gem built in by default.

One no longer has to make calls :as => :admin, nor do you need the attr_accessible :user_attribute, :as => admin in your model. The reason for this is that, by default, rails apps now have 'security' for every attribute on models. You have to permit the attribute you want to access / modify.

All you need to do now is call permit during update_attributes:

@user.update_attributes(params[:user], permit[:user_attribute])

or, to be more precise:

@user.update_attributes(params[:user].permit(:role_ids))

This single line, however, allows any user to modify the permitted role. You have to remember to only allow access to this action by an administrator or any other desired role through another filter such as the following:

authorize! :update, @user, :message => 'Not authorized as an administrator.'

. . . which would work if you're using Devise and CanCan for authentication and authorization.

于 2013-07-03T14:11:58.273 回答
37

如果您创建一个新的 Rails 4 站点,您会注意到生成的控制器现在包含一个私有方法,您可以使用它来接收经过清理的参数。这是一个很好的成语,看起来像这样:

private

  def user_params
    params.require(:user).permit(:username, :email, :password)
  end

允许批量分配的旧方法是使用类似的东西:

attr_accessible :username, :email, :password

在您的模型上将某些参数标记为可访问。

升级

要升级,您有多种选择。您最好的解决方案是使用 params 方法重构您的控制器。不过,这可能比你现在有时间做更多的工作。

受保护的属性宝石

另一种方法是使用 protected_attributes gem 来恢复 attr_accessible 方法。这使得升级路径更加顺畅,但有一个主要警告。

主要警告

在 Rails 3 中,任何没有 attr_accessible 调用的模型都允许所有属性。

在带有 protected_attributes gem 的 Rails 4 中,这种行为是相反的。任何没有 attr_accessible 调用的模型都限制了所有属性。您现在必须在所有模型上声明 attr_accessible。这意味着,如果您没有使用 attr_accessible,则需要将其添加到所有模型中,这可能与创建 params 方法一样多。

https://github.com/rails/protected_attributes

于 2013-12-18T13:11:03.643 回答
9

这个问题也可能是由Cancan gem引起的

只需添加到 application_controller.rb

before_filter do
  resource = controller_name.singularize.to_sym
  method = "#{resource}_params"
  params[resource] &&= send(method) if respond_to?(method, true)
end

无需对代码进行任何进一步修改即可工作从这里获得:https ://github.com/ryanb/cancan/issues/835#issuecomment-18663815

于 2014-01-24T10:46:10.900 回答
5

不要忘记将新的 user_params 方法添加到控制器操作中:

  def create
    @user = User.new(user_params)

    @user.save
    redirect_to 'wherever'
  end
于 2014-10-22T16:34:19.063 回答
-2
def create
  @user = User.create(user_params)
  ....
end

def update
  @user = User.find(params[:id])
  if @user.update_attributes(blog_params)
    redirect_to home_path, notice:  "Your profile has been successfully updated."
  else
    render action: "edit"
  end
end

private
  def user_params
    params.require(:user).permit(:name, :age, :others)
  end
于 2014-12-14T16:39:40.583 回答