gpt4 book ai didi

ruby-on-rails - 如何在父模型的验证错误后显示嵌套表单验证错误?

转载 作者:行者123 更新时间:2023-12-03 15:19:15 43 4
gpt4 key购买 nike

使用 Ruby on Rails 4.2,我有一个嵌套表单。在测试整个表单的验证时,我注意到嵌套表单的验证错误出现在验证错误列表的顶部,主表单的验证错误出现在下面。

这是声明它们的相反顺序(因为 fields_for 必须出现在父 form_for 的范围内),所以它看起来像这样:

[name        ]
[description ]
[others ]
[nested #1 ]
[nested #2 ]

但是验证错误看起来像这样(使用空白作为示例验证错误):
  • NestedModelName 嵌套 #1 不能为空。
  • NestedModelName 嵌套 #2 不能为空。
  • 名称不能为空。
  • 描述不能为空。
  • 其他不能为空。

  • 这会让用户感到困惑,因为错误的出现与它们在页面上的显示方式是无序的。它不期望它根据它在表单中出现的位置处于正确的位置,因为它显然只是依次验证每个模型,但由于嵌套表单模型通常是从​​属的,所以至少应该将它添加到结束而不是在开始时出现。有没有办法让嵌套表单验证错误出现在父表单验证错误之后?

    附加信息:

    使用以下内容在 View 中显示错误:

    application_helper.rb
    def error_messages(resource)

    return '' if resource.errors.empty?

    messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
    sentence = I18n.t('errors.messages.not_saved',
    count: resource.errors.count,
    resource: resource.class.model_name.human.downcase)
    html = <<-HTML
    <div class="validation-error alert alert-danger alert-dismissable fade in alert-block">
    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button>
    <p>#{sentence}</p>
    <ul>
    #{messages}
    </ul>
    </div>
    HTML

    end

    并在每个包含表单的 View 文件中使用它:
    <%= error_messages(@model) %>

    最佳答案

    更新 1 :

    我发现如果您不需要担心 i18n 和应用程序文本的翻译,februaryInk 的答案非常接近正确。如果你把 has_many :child_model在所有验证下方,验证将以正确的顺序显示。但是,full_messages似乎没有使用语言环境文件翻译模型或属性名称,因此如果您需要翻译错误消息(我这样做),我的回答似乎仍然是一个不错的解决方案。

    更新 2:

    在发布第一次更新后才意识到我可以简化生成 messages 的代码通过删除使用更新 1 中的发现进行排序的部分来列出很多内容,并只保留进行翻译的部分。所以这是我的新解决方案,它结合了我的更新 1 和我的原始解决方案。关于 config/locales/xx.yml 的所有其他信息和 config/application.rb此更新解决方案的文件仍然与原始解决方案相同。

    应用程序/模型/parent_model.rb

    ...

    validates :name, # validations hash
    validates :description, # validations hash
    validates :others, # validations hash

    has_many :child_models
    accepts_nested_attributes_for :child_models

    ...

    应用程序/模型/child_model.rb
    ...

    validates :nested_1, # validations hash
    validates :nested_2, # validations hash

    ...

    app/helpers/application_helper.rb
    messages = resource.errors.messages.keys.map {|value| error_message_attribute(resource, value) + I18n.t('space') + resource.errors.messages[value].first}.map { |msg| content_tag(:li, msg) }.join

    private
    def error_message_attribute(resource, symbol)
    if symbol.to_s.split(".").length > 1
    model_name, attribute_name = symbol.to_s.split(".")
    model_class = model_name.singularize.camelize.constantize
    model_class.model_name.human + I18n.t('space') + model_class.human_attribute_name(attribute_name).downcase
    else
    resource.class.human_attribute_name(symbol)
    end
    end

    更新结束

    我对我的 error_messages 做了一些更改 application_helper.rb中的函数现在一切都按照我想要的方式工作:主表单验证错误在顶部,嵌套表单验证错误在这些错误之下,错误的顺序不会改变,除了将嵌套表单错误移动到主表单错误下。

    我的解决方案是更改 messages =输入 error_messages如下所示,并添加一个私有(private)辅助方法。 (这可能应该被分解成几个部分,以便于阅读和理解,但我在控制台中构建它以获得我想要的内容,然后直接从那里粘贴)。

    app/helpers/application_helper.rb
    messages = Hash[resource.errors.messages.keys.map.with_index(1) { |attribute, index| [attribute, [index, attribute.match(/\./) ? 1 : 0]] }].sort_by {|attribute, data| [data[1], data[0]]}.collect { |attributes| attributes[0]}.map {|value| error_message_attribute_name(resource, value) + I18n.t('space') + resource.errors.messages[value].first}.map { |msg| content_tag(:li, msg) }.join

    private
    def error_message_attribute_name(resource, symbol)
    if symbol.to_s.split(".").length > 1
    model_name, attribute_name = symbol.to_s.split(".")
    model_class = model_name.singularize.camelize.constantize
    model_class.model_name.human + I18n.t('space') + model_class.human_attribute_name(attribute_name).downcase
    else
    resource.class.human_attribute_name(symbol)
    end
    end

    此解决方案也适用于其他语言环境,因为我使用了 I18n得到所有的名字。您还必须添加以下内容:

    配置/语言环境/en.yml
    en:
    space: " "

    这样模型和属性名称将在单词之间有或没有空格的语言中正确处理(我需要支持的第一个语言环境是中文,它在单词之间没有空格)。例如,如果您确实需要支持中文,则可以使用:

    config/locales/zh.yml
    zh:
    space: ""

    如果您不必支持这种情况, I18n.t('space') 的所有实例可以替换为 " " .模型和属性名称也可以翻译为,但如果您不需要支持英语以外的语言环境,则无需执行任何操作(尽管您可以使用 en.yml 文件更改模型名称或显示的属性)。

    en.yml 为例使用常见的作者/书籍示例更改显示的名称:

    配置/语言环境/en.yml
    en:
    activerecord:
    models:
    author: "writer"
    book: "manuscript"
    attributes:
    author:
    name: "non de plume"
    book:
    name: "title"
    published: "year"

    在这个例子中是默认的,没有上述添加到 en.yml , 将会:
  • 名称不能为空。
  • 书名不能为空。
  • 出版的书不能为空。

  • 但是有了以上对 en.yml 的补充这将是:
  • Nom de plume 不能为空。
  • 稿件标题不能为空。
  • 稿件年份不能为空。

  • 当然,如果您有 zh.yml带有适当翻译的文件,您在其中的任何内容都会显示出来。

    如果您确实需要支持多个语言环境,请不要忘记将以下内容添加到 config/application.rb (这部分只是表面测试,可能需要一些额外的配置):

    配置/应用程序.rb
    config.i18n.available_locales = [:zh, :en]
    config.i18n.default_locale = :en

    关于ruby-on-rails - 如何在父模型的验证错误后显示嵌套表单验证错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30181303/

    43 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com