0

我在如何验证数组字段的成员中找到了以下代码?.

# Validates the values of an Enumerable with other validators.
# Generates error messages that include the index and value of
# invalid elements.
#
# Example:
#
#   validates :values, enum: { presence: true, inclusion: { in: %w{ big small } } }
#
class EnumValidator < ActiveModel::EachValidator

  def initialize(options)
    super
    @validators = options.map do |(key, args)|
      create_validator(key, args)
    end
  end

  def validate_each(record, attribute, values)
    helper = Helper.new(@validators, record, attribute)
    Array.wrap(values).each do |value|
      helper.validate(value)
    end
  end

  private

  class Helper

    def initialize(validators, record, attribute)
      @validators = validators
      @record = record
      @attribute = attribute
      @count = -1
    end

    def validate(value)
      @count += 1
      @validators.each do |validator|
        next if value.nil? && validator.options[:allow_nil]
        next if value.blank? && validator.options[:allow_blank]
        validate_with(validator, value)
      end
    end

    def validate_with(validator, value)
      before_errors = error_count
      run_validator(validator, value)
      if error_count > before_errors
        prefix = "element #{@count} (#{value}) "
        (before_errors...error_count).each do |pos|
          error_messages[pos] = prefix + error_messages[pos]
        end
      end
    end

    def run_validator(validator, value)
      validator.validate_each(@record, @attribute, value)
    rescue NotImplementedError
      validator.validate(@record)
    end

    def error_messages
      @record.errors.messages[@attribute]
    end

    def error_count
      error_messages ? error_messages.length : 0
    end
  end

  def create_validator(key, args)
    opts = {attributes: attributes}
    opts.merge!(args) if args.kind_of?(Hash)
    validator_class(key).new(opts).tap do |validator|
      validator.check_validity!
    end
  end

  def validator_class(key)
    validator_class_name = "#{key.to_s.camelize}Validator"
    validator_class_name.constantize
  rescue NameError
    "ActiveModel::Validations::#{validator_class_name}".constantize
  end
end

这是我发现验证期望数组的rails表单输入的唯一有效方法。问题是无效条目的错误消息不是干净的闪存消息,而是典型的 rails 错误页面:

无效条目的错误消息

例如,我的表单有一个多选输入字段,用户可以在其中输入列表中的多个标签。如果用户输入了不在列表中的标签,我希望进行验证并告知用户他们必须从列表中选择一个项目。如何将错误消息更改为干净的 Flash 消息?

4

1 回答 1

0

验证器似乎正在引发错误,而不是简单地将错误消息添加到错误堆栈中。我建议包装update_attributes block in abegin/rescue/end` 块。

要更改消息,您可以采用两种方法:

  1. 您可以自定义EnumValidator使用您的语言环境文件中的键,以便每个条目可能会说“元素 %{count} 不在列表中”之类的内容。您应该能够自定义activerecord.errors.messages.inclusion消息的“不在列表中”部分。对于“元素 0 (rails)”部分,您可以硬编码该短语,如当前实现的那样(不推荐),或者通过添加一个键来再次使用语言环境文件enum_element,然后在您的 EnumValidator 中调用I18n.translate(:'activerecord.errors.messages.enum_element', count: @count, value: value).

  2. 验证后,检查errors.keys可枚举列上的问题。如果您发现错误,请删除这些键并为该键添加您自己的消息。

至于您的表单,听起来您正在使用动态表单构建器。as: :select如果是 SimpleForm,您可以尝试使用该选项指定输入应为的确切类型。

于 2013-11-12T18:45:43.667 回答