5

我有以下型号:

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 个级别。第三级给了我一个问题。

错误按预期触发,但是当错误触发 requires_at_least_one_department 时,文本显示

评估机构基地 请至少选择一个部门

消息应为“请至少选择一个部门”。

如何删除“评估机构库”?

4

4 回答 4

6

在 Rails 3.2 中,如果您查看方法 full_message 的实现,您会看到它通过 I18n 显示错误消息,格式为“%{attribute} %{message}”。

这意味着您可以自定义 I18n 语言环境中的显示格式,如下所示:

activerecord:
  attributes:
    evaluation_institutions:
      base: ''

这将摆脱您想要的前缀“评估机构基础”。

于 2012-05-08T21:39:34.070 回答
2

如果有人正在寻找不涉及猴子修补的解决方案,这就是我在部分错误中所做的。我只是在带有错误的属性名称中查找“base”,如果它存在,我只发布消息,否则我构建 full_message。现在,如果您的属性名称中有基础,这将不起作用,但我没有,所以这对我有用。这有点hacky,但这个问题的其他解决方案也是如此。

<% 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 %>
于 2014-08-06T00:39:21.530 回答
1

在 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,请尝试以下操作(除非您的表单 gem 像 dynamic_form 一样覆盖 errors.full_messages):

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', ':')

欢迎提出建议。

于 2012-04-26T03:14:28.300 回答
0

这是一个较老的问题,但是这个问题在 Rails 6 中再次让我感到困惑,所以在这里发布我的解决方案,因为这是涵盖该问题的最相关的 SO 帖子。

示例:保存顶级类:包含“Child”集合的“Parent”,其中“Child”具有自定义验证方法:

例如

class Parent < ActiveRecord::Base
  has_many :children
    accepts_nested_attributes_for :children, allow_destroy: true, reject_if: :all_blank
end

class Child < ActiveRecord::Base
  belongs_to :parent
  validate :custom_method

  def custom_method
    errors.add(:base, :error_symbol)
  end
end

需要以下内容:

  1. 为“error_symbol”提供语言环境条目
  2. 防止儿童呈现为“儿童基地......”的错误

解决方案

首先,添加config.active_model.i18n_customize_full_message = true到您的 application.rb 文件。

然后,以下语言环境文件可以覆盖这两个消息并防止将“Base”附加到集合中。

# config/locales/en.yml
en:
  activerecord:
    errors:
      models:
        parent/children:
          format: 'Child: %{message}'
        child:
          error_symbol: "Error message goes here"

有趣的是,这里似乎与 有一些交互accepts_nested_attributes_for,因为我只能在使用单个 params 对象创建父级和子级时重现此问题。

如果这对您不起作用,或者您有更复杂的问题,请查看ActiveModel/lib/active_model/errors.rbfull_message方法。

这应该告诉您是否:

  1. 有问题的课程正确地选择了该课程的 i18n 格式
  2. 它使用什么键来查看语言环境文件。
于 2020-06-29T10:36:59.993 回答