ActiveModel :: ForbiddenAttributesError使用update_attributes创建了params hash

我正在尝试使用simple_form编辑/更新模型记录,但表单不会直接更改模型字段。 相反,我提供了几个check_box_tag字段,用于告知更新需要更改的字段。 因此,更新未收到可用于更新属性的params [:device]哈希。 我试图创建这个哈希,但是当我发出@ device.update_attributes(params [:device])时,我得到了ForbiddenAttributesError。

我相信我的强参数列表是正确的。 如果我允许在编辑视图中处理一个模型字段(名称),我会收到预期的参数[:device]哈希,一切正常。 如果我禁用该字段,因为我不希望它被更改,那么我需要自己创建该哈希并收到错误。 当我查看我创建的哈希时,它看起来等同于视图传递的哈希。 我不明白为什么会失败。

环境是Ruby 2.0.0,Windows 8.1上的Rails 4.1和RubyMine 6.3。

表单是:

  Device:        

我发送f.input:name,disabled:false并允许视图生成params [:device]时收到的params [:device]是:

 ActionController::Parameters (3 element(s)) "{"name"=>"D105", "password"=>"D105Dvgr", "password_confirmation"=>"D105Dvgr"}" 

一切正常。

我创建的参数[:device]是:

 ActionController::Parameters (3 element(s)) "{"name"=>"D106", "password"=>"D106VdAd", "password_confirmation"=>"D106VdAd"}" 

并且,我收到禁用属性错误,即使我看到两者之间没有区别。

更新是:

 class DevicesController  'Not authorized as an administrator.' @device = Device.find(params[:id]) pwd_msg = "" if params[:chg_pwd] pwd_gen = @device.device + SecureRandom.urlsafe_base64(15).tr('lIO0=_\-', 'sxyzEUM').first(4) params[:device] = {name: @device.name} if params[:device].nil? params[:device][:password] = pwd_gen params[:device][:password_confirmation] = pwd_gen pwd_msg = ", new password is #{pwd_gen}" end if @device.update_attributes(params[:device]) params[:is_admin] ? @device.add_role(:admin) : @device.remove_role(:admin) flash[:notice] = ["Device updated" + pwd_msg] redirect_to devices_path else @device.errors.messages.each do |key, value| flash[:alert] = ["Unable to update device"] @device.errors.messages.each do |key, value| flash[:alert] << key.to_s.capitalize + " " + value[0] end end redirect_to devices_path end end private def device_params params.require(:device).permit(:device, :name, :email, :password, :password_confirmation, :encrypted_password, :salt, :role_ids, :is_admin, :chg_pwd) # TODO minimize when update is working end end 

该模型是:

 class Device  login.downcase }]).first else where(conditions).first end end end 

新信息:我忽略了在ApplicationController中提供的信息。 Anton Trapp的这个修复程序处理了尚未完全兼容Rails 4的gem的强大参数:

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

我发现使用建议的解决方案:

 @device.update_attributes(device_params) 

如果更新模型字段,则不起作用。 结果是“param not found:device”。 如果没有更新模型字段,它确实有效。 所以,整个问题都引出了真正错误的问题。

DevicesController#update action中,更改

 @device.update_attributes(params[:device]) 

 @device.update_attributes(device_params) 

在使用Rails 4.1 ,需要将要在数据库中插入/更新的属性列入白名单。 当您将属性直接传递给update_attributes方法而不允许它们时,您收到了ActiveModel::ForbiddenAttributesError

UPDATE

要解决param not found: device

  def device_params if params[:device] params.require(:device).permit(:device, :name, :email, :password, :password_confirmation, :encrypted_password, :salt, :role_ids, :is_admin, :chg_pwd) # TODO minimize when update is working end end 

修复是将字段作为attr_accessor添加到模型,而不是数据库,以便可以在表单中正确使用它。

  attr_accessor :is_admin, :chg_pwd 

然后将视图修改为:

 <%= simple_form_for @device do |f| %> <%= controller.action_name.capitalize %> Device: <%= f.input :name, disabled: true %> <%= f.input :is_admin, as: :boolean, checked_value: true, unchecked_value: false %> <%= f.input :chg_pwd, as: :boolean, checked_value: true, unchecked_value: false %> <%= f.button :submit %> <% end %> 

然后,由于Anton Trapp的应用程序控制器代码:

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

我能够更新设备控制器中的字段,如下所示:

 @device.update_attributes(params[:device])