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。
表单是:
我发送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| %> <%= 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])