change validation error from active record error view page to clean flash message

做~自己de王妃 提交于 2019-12-13 06:13:47

问题


I found the following code at How do I validate members of an array field? .

# 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

It is the only way that works i have found of validating a rails form input that is expecting an array. The problem is that the error message for invalid entries is not in a clean flash message but the typical rails error page:

For example, my form has a multiple select input field in which the user can enter several tags from a list. If the user enters tags that are not from the list, i want the validation to occur and for the user to be told that they must pick an item from the list. How do I change the error message into a clean flash message?


回答1:


It appears that the validator is raising an error instead of simply adding error messages to the errors stack. I'd recommend wrapping the update_attributes block in abegin/rescue/end` block.

For changing the message, you can take two routes:

  1. You could customize the EnumValidator to use keys from your locale file so that each entry might say something like the "element %{count} is not in the list". You should be able to customize activerecord.errors.messages.inclusion for the "is not in the list" portion of the message. For the "element 0 (rails)" portion, you could either hard-code the phrase, as is currently implemented (not recommended) or make use of the locale file again by adding a key for say, enum_element, then in your EnumValidator, call I18n.translate(:'activerecord.errors.messages.enum_element', count: @count, value: value).

  2. After validation, check errors.keys for for issues on your enumerable column. If you find errors, remove those keys and add your own message for that key.

As for your form, it sounds like you're using a dynamic form builder. If it's SimpleForm, you could try specifying the exact type the input should be with the as: :select option.



来源:https://stackoverflow.com/questions/19913373/change-validation-error-from-active-record-error-view-page-to-clean-flash-messag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!