我很清楚,当一个表单中的验证失败时:发生的事情是与您的对象关联的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如何做到这一点?我无法在此找到相关文档,也无法在线查找有关幕后魔术的任何资源。
答案 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 }
这由ActiveModelInstanceTag
:https://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-view和https://github.com/rails/rails/blob/7c3a99eeca07f602bb1e5659656e8eab0a4eacfe/guides/source/active_support_core_extensions.md#cattr_reader-cattr_writer-and-cattr_accessor。
工作中没有魔力;它评估所有模型。