Rails validation error messages: Displaying only one error message per field

后端 未结 13 817
情话喂你
情话喂你 2020-12-07 17:08

Rails displays all validation error messages associated with a given field. If I have three validates_XXXXX_of :email, and I leave the field blank, I get three

相关标签:
13条回答
  • 2020-12-07 17:43

    Or you can simply modify the array (with 'bang' method delete_at), so everything after stays default rails, i18n etc.

    <% @article.errors.keys.each { |attr| @article.errors[attr].delete_at(1) } %> 
    

    Complete working code:

    <% if @article.errors.any? %>
      <% @article.errors.keys.each { |attr| @article.errors[attr].delete_at(1) } %> 
       <ul>
        <% @article.errors.full_messages.each do |msg| %>
         <li><%= msg %></li>
        <% end %>
      </ul>
    <% end %>
    
    0 讨论(0)
  • 2020-12-07 17:47

    Add a method to ActiveModel::Errors class

    module ActiveModel
      class Errors
        def full_unique_messages
          unique_messages = messages.map { |attribute, list_of_messages| [attribute, list_of_messages.first] }
          unique_messages.map { |attribute_message_pair| full_message *attribute_message_pair }
        end
      end
    end
    

    Add it to a file, like lib/core_ext/rails/active_model/errors.rb. Create a file config/initializers/core_ext.rb and add a require "core_ext/rails/active_model/errors.rb" to it.

    0 讨论(0)
  • 2020-12-07 17:48

    Imo simplier is:

    <% @model.errors.each do |attr, msg| %>
      <%= "#{attr} #{msg}" if @model.errors[attr].first == msg %> 
    <% end %>
    
    0 讨论(0)
  • 2020-12-07 17:49

    I wrote a custom helper

    def display_error(field)
        if @user.errors[field].any?
            raw @user.errors[field].first+"<br>"
        end
    end
    

    and then I use it in view under the text field like so

    <%= display_error(:password) %>
    
    0 讨论(0)
  • 2020-12-07 17:50
    # Extracts at most <strong>one error</strong> message <strong>per field</strong> from the errors-object.
    # @param  [ActiveModel::Errors] the_errors_object The errors-object.
    # @raise  [ArgumentError] If the given argument is not an instance of ActiveModel::Errors.
    # @return [Array] A string-array containing at most one error message per field from the given errors-object.
    def get_one_error_per_field(the_errors_object)
      if the_errors_object.is_a? ActiveModel::Errors    
        errors = {}  
        the_errors_object.each do |field_name, associated_error|
          errors[field_name] = the_errors_object.full_message(field_name, associated_error) unless errors[field_name]
        end 
        return errors.values
      else
        raise ArgumentError.new('The given argument isn\'t an instance of ActiveModel::Errors!')
      end 
    end 
    
    0 讨论(0)
  • 2020-12-07 17:51

    Bert over at RailsForum wrote about this a little while back. He wrote the code below and I added some minor tweaks for it to run on Rails-3.0.0-beta2.

    Add this to a file called app/helpers/errors_helper.rb and simply add helper "errors" to your controller.

    module ErrorsHelper
    
      # see: lib/action_view/helpers/active_model_helper.rb
      def error_messages_for(*params)
            options = params.extract_options!.symbolize_keys
    
            objects = Array.wrap(options.delete(:object) || params).map do |object|
              object = instance_variable_get("@#{object}") unless object.respond_to?(:to_model)
              object = convert_to_model(object)
    
              if object.class.respond_to?(:model_name)
                options[:object_name] ||= object.class.model_name.human.downcase
              end
    
              object
            end
    
            objects.compact!
            count = objects.inject(0) {|sum, object| sum + object.errors.count }
    
            unless count.zero?
              html = {}
              [:id, :class].each do |key|
                if options.include?(key)
                  value = options[key]
                  html[key] = value unless value.blank?
                else
                  html[key] = 'errorExplanation'
                end
              end
              options[:object_name] ||= params.first
    
              I18n.with_options :locale => options[:locale], :scope => [:errors, :template] do |locale|
                header_message = if options.include?(:header_message)
                  options[:header_message]
                else
                  locale.t :header, :count => count, :model => options[:object_name].to_s.gsub('_', ' ')
                end
    
                message = options.include?(:message) ? options[:message] : locale.t(:body)
    
                error_messages = objects.sum do |object|
                  object.errors.on(:name)
                  full_flat_messages(object).map do |msg|
                    content_tag(:li, ERB::Util.html_escape(msg))
                  end
                end.join.html_safe
    
                contents = ''
                contents << content_tag(options[:header_tag] || :h2, header_message) unless header_message.blank?
                contents << content_tag(:p, message) unless message.blank?
                contents << content_tag(:ul, error_messages)
    
                content_tag(:div, contents.html_safe, html)
              end
            else
              ''
            end
      end
    
      ####################
      #
      # added to make the errors display in a single line per field
      #
      ####################
      def full_flat_messages(object)
        full_messages = []
    
        object.errors.each_key do |attr|
          msg_part=msg=''
          object.errors[attr].each do |message|
            next unless message
            if attr == "base"
              full_messages << message
            else
              msg=object.class.human_attribute_name(attr)
              msg_part+= I18n.t('activerecord.errors.format.separator', :default => ' ') + (msg_part=="" ? '': ' & ' ) + message
            end
          end
          full_messages << "#{msg} #{msg_part}" if msg!=""
        end
        full_messages
      end
    
    end
    
    0 讨论(0)
提交回复
热议问题