当fields_for中的验证失败时,如何在表单中添加field_with_errors div

时间:2017-03-22 22:20:31

标签: ruby-on-rails ruby

我很清楚,当一个表单中的验证失败时:发生的事情是与您的对象关联的errors哈希获得一个新的键,该键被神奇地映射到该对象的无效{{1 }}。该密钥的attribute是该失效的相关错误消息。

以上所有内容都在Working with Validation Errors Rails Guide

中得到了很好的解释

下一部分是对我没有意义的。可悲的是:rails似乎以某种方式查看错误哈希中的键,将这些键映射到相应的表单标签和输入,然后使用value包装这些无效的表单标签和输入。

我想弄清楚这种魔法是如何起作用的。

更具体一点:我想知道当<div class="field_with_errors"> ... </div>关联的表单中存在field_with_errors时,rails能够如何正确映射fields_for

示例:假设我有以下关联:

has_many

然后,我有一个# models/user.rb class User < ApplicationRecord has_many :user_emails end # models/user_email.rb class UserEmail < ApplicationRecord belongs_to :user validates_presence_of :email_text end 表格,其user 5 不同的嵌套fields_for记录。我们说其中两个user_email无效:

  • 表单将重新呈现,并且奇怪地user_emails div 仅应用到这两个无效的fields_with_errors记录,而不是 ALL 表单中的user_email条记录。

rails如何做到这一点?我无法在此找到相关文档,也无法在线查找有关幕后魔术的任何资源。

1 个答案:

答案 0 :(得分:1)

对象逐个传递field_error_proc,因此每个UserEmail都是单独评估的。这里定义了默认的proc规范:https://github.com/rails/rails/blob/7da8d76206271bdf200ea201f7e5a49afb9bc9e7/actionview/lib/action_view/base.rb#L144 as:

@@field_error_proc = Proc.new { |html_tag, instance| "<div class=\"field_with_errors\">#{html_tag}</div>".html_safe }

这由ActiveModelInstanceTaghttps://github.com/rails/rails/blob/92703a9ea5d8b96f30e0b706b801c9185ef14f0e/actionview/lib/action_view/helpers/active_model_helper.rb#L28调用:

Base.field_error_proc.call(html_tag, self)

请注意,此处self指的是正在评估的单个UserEmail对象。有关此proc的更多信息,请访问https://github.com/rails/rails/blob/09436fb6d6d188739b40ef120b4344106d81caf9/guides/source/configuring.md#configuring-action-viewhttps://github.com/rails/rails/blob/7c3a99eeca07f602bb1e5659656e8eab0a4eacfe/guides/source/active_support_core_extensions.md#cattr_reader-cattr_writer-and-cattr_accessor

工作中没有魔力;它评估所有模型。