Подавить "base" в тексте ошибки для пользовательской проверки вложенных атрибутов Rails - PullRequest
5 голосов
/ 10 мая 2011

У меня есть следующие модели:

class Evaluation < ActiveRecord::Base
    attr_accessible :product_id, :description, :evaluation_institutions_attributes

    has_many :evaluation_institutions, :dependent => :destroy  
    accepts_nested_attributes_for :evaluation_institutions, :reject_if => lambda { |a| a[:token].blank? }, :allow_destroy => true       

    validate :requires_at_least_one_institution

    private

      def requires_at_least_one_institution
        if evaluation_institution_ids.nil? || evaluation_institution_ids.length == 0
          errors.add_to_base("Please select at least one institution")
        end
      end    
end

class EvaluationInstitution < ActiveRecord::Base

  attr_accessible :evaluation_institution_departments_attributes, :institution_id

  belongs_to :evaluation

  has_many :evaluation_institution_departments, :dependent => :destroy  
  accepts_nested_attributes_for :evaluation_institution_departments, :reject_if => lambda { |a| a[:department_id].blank? }, :allow_destroy => true

  validate :requires_at_least_one_department

  private

    def requires_at_least_one_department
       if evaluation_institution_departments.nil? || evaluation_institution_departments.length == 0
         errors.add_to_base("Please select at least one department")
       end
    end

end

class EvaluationInstitutionDepartment < ActiveRecord::Base
  belongs_to :evaluation_institution
  belongs_to :department
end

У меня есть форма для оценки, которая содержит вложенные атрибуты для EvaluationInstitution и EvaluationInstitutionDepartment, поэтому моя форма вложена в 3 уровня. 3-й уровень доставляет мне проблемы.

Ошибки запускаются, как и ожидалось, но когда ошибка запускается для require_at_least_one_department, текст читается как

База оценочных учреждений Пожалуйста выберите хотя бы один отдел

В сообщении должно быть написано «Пожалуйста, выберите хотя бы один отдел».

Как удалить «База оценочных учреждений»?

Ответы [ 3 ]

6 голосов
/ 09 мая 2012

В Rails 3.2, если вы посмотрите на реализацию метода full_message, вы увидите, что он показывает сообщения об ошибках через I18n в формате "% {attribute}% {message}".

Это означает, что вы можете настроить отображаемый формат в ваших локалях I18n следующим образом:

activerecord:
  attributes:
    evaluation_institutions:
      base: ''

Это избавит от префикса «База институтов оценки», как вы хотели.

2 голосов
/ 06 августа 2014

Если кто-то ищет решение для этого, которое не включает исправление обезьян, вот что я сделал в своих частичных ошибках. Я просто ищу "base" в имени атрибута с ошибкой и, если он существует, я только отправляю сообщение, в противном случае я создаю full_message. Теперь это не сработает, если у вас есть атрибуты, у которых в имени есть база, но у меня нет, поэтому у меня это работает. Это немного глупо, но и другие решения этой проблемы.

<% if object.errors.any? %>
  <div id="error-explanation">
    <div class="alert alert-error">
      <ul>
        <% object.errors.each do |atr, msg| %>
          <li>
            <% if atr.to_s.include? "base" %>
              <%= msg %>
            <% else %>
              <%= object.errors.full_message(atr, msg) %>
            <% end %>
          </li>
        <% end %>
      </ul>
    </div>
  </div>
<% end %>
1 голос
/ 26 апреля 2012

Добавление следующего обезьяньего патча к инициализаторам сделало для меня работу в 3.2.3 с помощью dynamic_form:

class ActiveModel::Errors
  #exact copy of dynamic_form full_messages except 'attr_name = attr_name.sub(' base', ':')'
  def full_messages        
    full_messages = []

    each do |attribute, messages|
      messages = Array.wrap(messages)
      next if messages.empty?

      if attribute == :base
        messages.each {|m| full_messages << m }
      else
        attr_name = attribute.to_s.gsub('.', '_').humanize
        attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
        attr_name = attr_name.sub(' base', ':')
        options = { :default => "%{attribute} %{message}", :attribute => attr_name }

        messages.each do |m|
          if m =~ /^\^/
            options[:default] = "%{message}"
            full_messages << I18n.t(:"errors.dynamic_format", options.merge(:message => m[1..-1]))
          elsif m.is_a? Proc
            options[:default] = "%{message}"
            full_messages << I18n.t(:"errors.dynamic_format", options.merge(:message => m.call(@base)))
          else
            full_messages << I18n.t(:"errors.format", options.merge(:message => m))
          end            
        end
      end
    end

    full_messages
  end
end

Если вы не используете dynamic_form, попробуйте выполнить следующее (если ваш гем формы не переопределяет ошибки.full_messages, как и dynamic_form):

class ActiveModel::Errors        
    #exact copy of Rails 3.2.3 full_message except 'attr_name = attr_name.sub(' base', ':')'
    def full_message(attribute, message)
      return message if attribute == :base
      attr_name = attribute.to_s.gsub('.', '_').humanize
      attr_name = @base.class.human_attribute_name(attribute, :default => attr_name)
      attr_name = attr_name.sub(' base', ':')
      I18n.t(:"errors.format", {
        :default   => "%{attribute} %{message}",
        :attribute => attr_name,
        :message   => message
      })
    end   
end

Единственное изменение исходного кода - это следующая строка:

attr_name = attr_name.sub(' base', ':')

Предложения приветствуются.

...