在验证错误时预期数字时重新显示无效数据条目

时间:2016-08-10 15:34:15

标签: ruby-on-rails ruby

让我们说用户提交表单。其中一个字段无效,因此表单会重新呈现。在重新呈现表单的过程中:我检查该属性的提交值是否无效。如果是这样:那么显示带有一些附加文本的无效数据输入。

这是我到目前为止所拥有的。它很接近,但没有完全运作:

<%= form_for(blog) do |f| %>
  <div class="field">
    <%= f.label :age %>

    <% if f.object.age %>
      <% if f.object.errors.include?(:age) %>
        <%= f.text_field :age, value: "Submitted: #{f.object.age} was bad" %>
      <% else %>
        <%= f.text_field :age %>
      <% end %>
    <% else %>
      <%= f.text_field :age %>
    <% end %>

  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

所以我说:“嘿Rails:如果用户已提交此表单,用户为此age属性提交的值无效,则重新呈现输入中提交的值以及一些其他文本。“

我遇到的问题是它不会正确显示错误输入。例如:如果用户在输入字段中输入“abcd”,那么当表单在验证失败时重新呈现时,输入字段应该说:“已提交:abcd是坏的”。相反,它说“提交:0很糟糕”。

我很接近。最终的问题是:为什么显示0?为什么不显示"abcd"?接下来的问题是:“如何让它显示"abcd"

这是因为我有以下验证吗? :

    validates :age, numericality: true

如果是这样:我如何进行验证以确保它是一个数字,还重新显示用户输入的值?

2 个答案:

答案 0 :(得分:0)

这是失败的,因为您在插值字符串中调用f.object.age,而不是提交的值。

由于您正在验证年龄的数字,因此'abcd'输入将永远不会通过验证,因此永远不会保存。

因此,当您在该对象上调用.age时,您只获得默认值,或者通过验证并保存的最后一个值。

显示错误的更简单方法是:

'abcd'

您还可以尝试添加自定义错误消息:

f.object.errors.full_messages_for(:age)

答案 1 :(得分:0)

这很有效。只需从params哈希中获取提交的值:

<div class="field">
  <%= f.label :age %>

  <% if f.object.age %>
    <% if f.object.errors.include?(:age) %>
      <%= f.text_field :age, value: "Submitted #{params[:blog][:age]} is bad" %>
     <% else %>
      <%= f.text_field :age %>
    <% end %>
  <% else %>
    <%= f.text_field :age %>
  <% end %>
</div>

f.object.age似乎不起作用,因为age属性属于integer类型。因为:在age属性的writer方法中:

def age=(value)
  ...
end

在该setter中的某个地方可能发生的是rails试图将提交的值转换为:to_i。当您对字符串执行to_i时,它会返回0,因此当您尝试f.object.age时,它将返回0,因为作者尝试转换字符串。

另一个棘手的问题是text_field方法。 Rails在那里有一些魔力。例如:如果没有任何特殊内容:以下成功显示提交的值而不是0

<%= f.text_field :age %>

因此,在text_field方法中的某个位置,rails会查看age的该属性是否无效,如果是,则指定为提交的value 价值。

如果没有深入研究rails源代码,很难说text_field如何确定该属性是否先前已提交,以及提交的值是否无效。因此:如果在rails源代码中挖了一个,我相信一旦你弄清楚text_field如何显示提交的值(例如'abcd'而不是转换后的值),你可以清理上面的条件。设定者(例如:'0')。

尽管如此:上面的代码可以正常工作并完成所需的工作。