【问题标题】:Validation Error Messages for belongs_to Assocations made easybelongs_to 关联的验证错误消息变得容易
【发布时间】:2016-08-18 13:14:04
【问题描述】:

我的应用程序中有相当多的 belongs_to 关联,其中一些是可选的(即关联可以为 nil),有些是强制性的(关联必须是有效的父记录。

我最初的方法是使用我自己的验证方法来验证给定的 id(这里是强制关联)

belongs_to :category

validates :category_id, 
  presence: true

validate given_category_exists

def given_category_exists
  if category_id.present?
    errors.add( :category_id, 'must be present' ) \
      Category.exists?( category_id )
  end
end

然后我发现如果我对关联使用存在性检查,Rails 会为我执行此操作,因此我可以省略我自己的验证方法:

belongs_to :category

validates :category,
  presence: true

但现在,生成的错误消息将简单地说明:Category can't be blank。这里的问题是:(1)我可以提供更有用的信息吗? (2) 如何插入我自己的属性翻译? Category 是 validates 方法生成的默认标签,can't be blank 是 :blank 的默认错误文本。

另一个问题:表单中的相关输入字段未标记为“field_with_errors”,因为该字段是用属性名称而不是关联名称标识的。

使用标准的处理方式,我将在我的 I18n 翻译文件中添加一个附加属性,用于关联名称 category,并添加一个替换标准消息:

en:
  activerecord:
    models:
      attributes:
        my_model:
          category_id: 'This Category'
          category:    'This Category'

    errors:
      models:
        my_model:
          attributes:
            category:
              blank:  'must be specified.'

很多行可能会出错。而且我不喜欢添加实际上不是属性而是关联名称的肤浅属性的想法。

有没有更简单的方法?

【问题讨论】:

  • 不,您可能使用最简单的方法来防止以后的麻烦。

标签: ruby-on-rails validation


【解决方案1】:

帖子很旧,但我仍然会写我的解决方案。 Rails 5 有一个 required 错误键,您可以使用它来覆盖那些属于关联的验证消息:

class MyModel < ApplicationRecord
  belongs_to :category
end

请注意,您实际上不需要在此处指定验证规则 (validates :category, presence: true)。要自定义您的消息,只需使用required 键:

en:
  activerecord:
    errors:
      models:
        my_model:
          attributes:
            category:
              required: "The category must be specified."

【讨论】:

  • 如何解决由于 Rails 将属性名称添加到消息中而将“必须指定类别”作为错误消息打印的问题?
  • @ChristopherOezbek 您可以像这样使用error message interpolation required: "The %{attribute} must be specified." 并将属性定义为en.activerecord.attributes.my_model.category = "Category"
【解决方案2】:

我的解决方案是覆盖 errors.add 方法,该方法被证明非常简单且非常有效。 Rails 关联包含所有需要的信息,我只需要在那里获取它。我什至可以使用对关联的 class_name 的引用来格式化我自己的错误消息!现在我的错误信息如下所示:

This Category must be one of the existing Categories.
  1. 添加新的标准错误消息:

    en:
      messages:
        blank_assoc: 'must be one of the existing %{assoc}'
    
  2. 将以下文件添加到 app/models/concerns 文件夹中

    module ActiveModelErrorsAdd
      def add( attribute, message = :invalid, options = {})
            if attribute != :base # that's the only other attribute I am using
          all_assocs = @base.class.reflect_on_all_associations( :belongs_to )
          this_assoc = nil
          all_assocs.each do |a|
            if a.name == attribute
              this_assoc = a
              break
            end
          end
        end
        if this_assoc.nil? # just use the standard
          super
        elsif message == :blank # replace with my own
          super( this_assoc.foreign_key, :blank_assoc,
            options.merge( assoc: this_assoc.klass.model_name.human ))
        else # use standard message but refer to the foreign_key!
          super( this_assoc.foreign_key, message, options )
        end
      end
    end
    
    class ActiveModel::Errors
      prepend ActiveModelErrorsAdd
    end
    
  3. 在需要的地方将此文件包含到模型中,您将收到关于所有 belongs_to 关联的漂亮错误消息。享受吧!

注意:此方法还会导致正确的输入字段被标记为“field_with_errors” - 即使它具有非标准外键!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-15
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-13
    相关资源
    最近更新 更多