禁止的属性在Rails 4遇到一种情况,在早期版本的Rails中会使用attr_accessible的情况下出现错误

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

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

用户在模型中具有以下attr_accessible行:

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

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

Rails 4现在具有默认内置的strong_parameters gem的特性。

不再需要拨打电话:as => :admin ,在模型中也不需要attr_accessible :user_attribute, :as => admin 。 原因是,默认情况下,rails应用程序现在对模型上的每个属性都具有“安全性”。 你必须permit你想要访问/修改的属性。

你现在需要做的就是在update_attributes调用permit

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

或者更确切地说:

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

然而,这一行允许任何用户修改permitangular色。 您必须记住只允许pipe理员或任何其他所需的angular色通过另一个筛选器访问此操作,如下所示:

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

。 。 。 如果您使用Devise和CanCan进行身份validation和授权,这将起作用。

如果你创build一个新的Rails 4站点,你​​会发现生成的控制器现在包含一个私有的方法,用来接收你的消毒参数。 这是一个很好的习惯,看起来像这样:

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

允许大规模分配的旧方法是使用如下的东西:

 attr_accessible :username, :email, :password 

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

升级

升级你有几个select。 你最好的解决scheme是用params方法重构你的控制器。 虽然这可能比你现在有更多的工作。

Protected_attributes gem

另一种方法是使用恢复attr_accessible方法的protected_attributes gem。 有一个主要的警告,这使得升级路线稍微平滑一些。

主要警告

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

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

https://github.com/rails/protected_attributes

这个问题也可能是由康康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

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

  def create @user = User.new(user_params) @user.save redirect_to 'wherever' end 
 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