2

这发生在我的 Rails 应用程序中,但我不确定这是否是 Rails 的问题,或者我是否误解了多部分表单应该如何工作。

这是(类似于)我的表格:

<%= form_for @user do |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>

User#name有一个存在验证。如果我访问users/1/edit,清空“名称”文本字段的值,然后单击提交,由于存在验证失败,没有任何更新。到现在为止还挺好。

但是现在我已经avatar向我的用户添加了一个属性(使用 Paperclip gem 进行文件存储),所以我相应地更新了表单:

<%= form_for @user do |f| %>
  <%= f.text_field :name %>
  <%= f.file_field :avatar %>
  <%= f.submit %>
<% end %>

现在,如果我去编辑用户并为 提交一个空白值name,验证不会失败。User#name保持它以前的值,但更新似乎仍然成功(即我没有收到有关失败验证的错误消息并且updated_at数据库中的时间戳得到更新。)

经过仔细检查,似乎当我file_field在表单中包含 a 时,它会在提交空白文本字段时改变表单的行为(可能是由于form_for现在输出带有 的表单enctype=-"multipart/form-data")。

file_field 存在时,提交空白name会将这些参数发送到服务器:

{ "id" => 1, "user" => { "name: "" }

这会导致类似于User.find(1).update_attributes(name: "")控制器中的内容,当然无法更新,因为 Rails 看到我们正在尝试将“名称”更新为空白字符串并且验证失败。

当它存在时,它会被提交:

{ "id" => 1, "user" => { }(加上关于头像文件的额外信息)

“名称”键根本不存在,因此控制器运行User.find(1).update_attributes()当然会通过,因为没有任何更新可能导致验证失败。

这是一个错误,还是一个功能?为什么将 enctype 更改为 multipart(假设这是问题的根源)会改变空白文本字段的行为方式?(我已经在 Chrome 和 FF 中对此进行了测试,fwiw。)如果这确实是预期的行为,我如何确保正确提交空白文本字段而不必在每个文本字段周围添加一堆乏味的样板?

(如果重要的话,我正在使用:Ruby 2.3.0、Rails 5.0.0.beta3、Paperclip 5.0.0.beta1,并且我已经在 Chrome 49 和 Firefox 45 中进行了测试)

4

3 回答 3

1

我有同样的问题,将 Rails 更新到最新版本修复了它。

于 2016-05-17T08:33:10.003 回答
0

我认为你可以做这样的事情

updated_user = User.new(your_params) # The new attributes is set to a new object record    
target_user = User.find(params[:id]) # the user you want to update
target_user = updated_user

    if target_user.save?
    ..
    else
    .. 

这样所有的验证都将被触发,并且活动记录将具有所有新属性,如果名称为空,它将捕获它

于 2016-04-08T14:47:13.370 回答
0

以下强参数方法不会带回删除的 :name 参数,但它应该防止表单模仿成功提交:

private
  def user_params
    params.require(:user).permit(:name, :avatar)
  end

这可以作为私有方法插入到用户控制器下。然后只需在 Update 方法中调用 user_params 即可。

于 2016-04-09T16:03:05.950 回答