禁止的属性在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))
然而,这一行允许任何用户修改permit
angular色。 您必须记住只允许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方法一样多。
这个问题也可能是由康康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