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 エラー ページにあることです。

無効なエントリのエラー メッセージ

たとえば、私のフォームには、ユーザーがリストから複数のタグを入力できる複数選択入力フィールドがあります。ユーザーがリストにないタグを入力すると、検証が行われ、リストからアイテムを選択する必要があることがユーザーに通知されます。エラー メッセージをクリーンなフラッシュ メッセージに変更するにはどうすればよいですか?

4

1 に答える 1

0

エラースタックにエラーメッセージを単に追加するのではなく、バリデーターがエラーを発生させているようです。update_attributes block in abegin/rescue/end` ブロックをラップすることをお勧めします。

メッセージを変更するには、次の 2 つの方法があります。

  1. ロケール ファイルのキーを使用するようにカスタマイズしてEnumValidator、各エントリに「要素 %{count} がリストにありません」などのメッセージが表示されるようにすることができます。activerecord.errors.messages.inclusionメッセージの「リストにない」部分をカスタマイズできるはずです。「要素 0 (レール)」の部分については、現在実装されているようにフレーズをハードコードする (推奨されません) か、たとえば のキーを追加してロケール ファイルを再度使用しenum_element、次に EnumValidator で呼び出します。I18n.translate(:'activerecord.errors.messages.enum_element', count: @count, value: value).

  2. 検証後errors.keys、列挙可能な列に問題がないか確認してください。エラーが見つかった場合は、それらのキーを削除し、そのキーに独自のメッセージを追加してください。

フォームに関しては、動的フォームビルダーを使用しているようです。SimpleForm の場合は、as: :selectオプションを使用して入力の正確なタイプを指定してみてください。

于 2013-11-12T18:45:43.667 に答える