我有以下型号:
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
我有一个评估表单,其中包含评估机构和评估机构部门的嵌套属性,因此我的表单嵌套为 3 个级别。 第三关给我一个问题。
错误按预期触发,但当错误触发requires_at_least_one_department时,文本显示
评估机构基地请 至少选择一个部门
该消息应为"请至少选择一个部门"。
如何删除"评估机构基础"?
在 Rails 3.2 中,如果你看一下方法 full_message 的实现,你会发现它通过 I18n 显示错误消息,格式为"%{attribute} %{message}"。
这意味着您可以在 I18n 语言环境中自定义显示的格式,如下所示:
activerecord:
attributes:
evaluation_institutions:
base: ''
这将摆脱您想要的前缀"评估机构基础"。
如果有人正在寻找不涉及猴子修补的解决方案,这是我在错误部分中所做的。我只是在带有错误的属性名称中查找"base",如果存在,我只发布消息,否则我构建full_message。现在,如果您有名称中包含 base 的属性,这将不起作用,但我不这样做,这对我有用。这有点笨拙,但这个问题的其他解决方案也是如此。
<% 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 %>
将以下猴子补丁添加到初始值设定项中为我完成了 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', ':')
欢迎提出建议。
这是一个较老的问题,但这个问题只是在 Rails 6 中再次咬了我,所以在这里发布我的解决方案,因为这是涵盖该问题的最相关的 SO 帖子。
示例:保存顶级类:"Parent"包含"Child"集合,其中"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
需要以下内容:
- 为"error_symbol"提供区域设置条目
- 防止将子项呈现为"子基数..."的错误
溶液
首先,将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
有一些交互,因为我只能在使用单个参数对象创建父项和子项时重现此问题。
如果这对您不起作用,或者您有更复杂的问题,请查看ActiveModel/lib/active_model/errors.rb
full_message
方法。
这应该告诉您是否:
- 有问题的类正确选取该类的 i18n 格式
- 它使用哪些键在区域设置文件中查找。