2016-04-08 37 views
0

这发生在我的Rails应用程序中,但我不确定这是Rails问题还是我误解了多部分表单应该工作。以多部分形式提交空字符串作为空字符串,不为空

这里的(像)我的表格:

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

User#name有存在验证。如果我访问users/1/edit,请清空'name'文本字段的值,然后单击submit,由于存在验证失败,因此不会更新任何内容。到现在为止还挺好。

但现在我已经添加了一个avatar属性我的用户(使用回形针宝石用于文件存储),所以我更新相应的形式:

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

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

仔细观察,似乎是我在表单中包含file_field,它会在提交空白文本字段时更改表​​单的行为(可能是由于form_for现在输出的格式为enctype=-"multipart/form-data")。

file_field目前,提交空白name发送这些PARAMS到服务器:

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

导致控制器,这当然无法更新像User.find(1).update_attributes(name: "")因为Rails认为我们试图将'name'更新为空字符串,并且验证失败。

目前,这种被提交:

{ "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。β1,我已经在Chrome 49和Firefox 45)

+0

奇怪的是,我无法重现你描述的行为。在我的情况下(Rails 4.2虽然),无论编码类型是什么形式,空名都是_always_作为空字符串发送:'“name”=>“”''。也许你可以在Rails 4上尝试相同的代码,以便可能发现Rails 5的行为变化(甚至是bug)? – BoraMa

+0

另请参阅我认为需要的[my edit](http://stackoverflow.com/posts/36501726/revisions),以便如果我误解了您,问题实际上是有意义的,并将其还原。 – BoraMa

+0

是的,你的编辑是正确的。感谢您捕捉我的错误。 – GMA

回答

1

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

+0

是的,我正在使用Rails 5.0.0的测试版本之一。升级到RC似乎已经修复了它。 – GMA

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 
    .. 

通过这一切的验证将被触发,活动记录将所有的新属性,如果名称为空白,它会抓住它

+0

不起作用。你的前三行在功能上等价于'target_user = User.new(your_params)',它将创建一个新用户,而不是更新现有用户 - 问题不在于'用户'无法捕获空白名称,问题当它不应该的时候,'params [:user] [:name]'首先是空白的(':name'不存在)。 – GMA

+0

是的,现在我明白了,听起来很奇怪,你是否尝试过其他类似carrierwave的宝石,并且发生了同样的行为? – amrdruid

0

下强PARAM方法不会带回下降:名称参数,但应防止形式从模仿成功提交:

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

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

+0

这不回答我的问题。我已经有了强参数的'_params'方法。 – GMA