我想显示来自Child模型的验证消息,它给了我基本的Child无效。我尝试了所有解决方案但都没有成功。 简而言之,这些模型是:
Class Parent
...
has_many :children, dependent: :destroy, inverse_of: :parent
accepts_nested_attributes_for :children, allow_destroy: true
end
Class Child
belongs_to :parent
validate :something
def something
check = # Here I check something
if check < 5
errors[:base] << "validation on children failed"
end
end
end
如果我将validates_associated :children
添加到Parent模型,那么我实际上会收到两条Children is invalid
条消息,这有点奇怪。
无论如何,我可以将此块添加到Parent模型中,并获取我想要添加到Parent:base错误列表的任何验证消息:
validate do |parent|
parent.children.each do |child|
check = # Here I check something
if check < 5
errors[:base] << "validation on children failed"
end
end
end
但是,我仍然会在Child模型的基础上得到验证错误消息,所以现在我们会有3条错误消息:“Children is invalidChildren is childrenvalidation on children failed”......丑陋。
由于我将块添加到Parent模型,我可以从Child模型中删除验证,从Parent中删除validates_associated :children
,然后保存实例将不会通过验证,但属于儿童模型没有验证,将保存/更新。
希望这清楚地解释。如果你能提供解决方案,那就太棒了!
更新1:关于accepts_nested_attributes_for
记录非常糟糕。正如我解释的那样,我在没有请求的情况下对我的nsted模型进行了验证。我相信原因是accepts_nested_attributes_for
实际上从嵌套模型运行验证。
这意味着无论验证类型如何,我从嵌套模型获得的所有验证消息都会给我一条消息。我可能会设法以某种方式调整该消息的输出,但它仍然是单个消息,并不是特定于嵌套模型遇到的问题。
话虽如此,accepts_nested_attributes_for
确实允许reject_if
参数。这对我没有帮助,因为我需要在嵌套模型上为多个条目运行唯一性验证(一个父母的许多子项都需要具有唯一名称)。
要点:
我认为我需要在子模型中运行验证,但是找到一种方法,通过accepts_nested_attributes_for,使用特定的消息向Parent模型报告。这本质上就是我在寻找的东西! 我想我需要编写一个自定义验证器。有什么想法吗?
答案 0 :(得分:2)
添加我的解决方案,因为我希望它对浏览此问题的人有帮助:
class Parent < AR
has_many :children, inverse_of: :parent
validates_associated :children, message: proc { |_p, meta| children_message(meta) }
def self.children_message(meta)
meta[:value][0].errors.full_messages[0]
end
private_class_method :children_message
end
class Child < AR
belongs_to :parent, inverse_of: :children
validates :name, presence: true
end
答案 1 :(得分:0)
建议的解决方案
这么简单的事情不应该那么烦人。我仍然没有找到任何优雅的解决方案,但我没有更多的时间浪费在这上面。 为了公平对待他人,我会发布我的(丑陋的)解决方案。注意,这个解决方案仍然需要工作。
我最终创建了一个从两个模型中收集错误的方法,而不是让Rails这样做。
def collect_errors
errors = []
if self.errors.any?
parent_errors = self.errors.full_messages
parent_errors.delete("YOURCHILDMODELNAME is invalid")
errors << parent_errors.join(", ")
end
self.children.each do |child|
if child.errors.any?
errors << child.errors.messages.values.join(", ")
end
end
return errors.join(", ")
end
然后我在每个模型上进行所有验证,在视图中我只显示收集的错误,而不是父模型错误:
flash[:warning] = "Failed to create Parent: #{@parent.collect_errors}"
答案 2 :(得分:0)
也可以组合错误消息:
@parent_model.children.each do |child_record|
child_record.errors.messages.each do |field, messages|
messages.each do |msg|
@parent_model.errors.add("#{child_record.id} #{field}", msg)
end
end
end
答案 3 :(得分:0)
ActiveModel Errors类现在具有副本!并合并!为此目的的方法。复制将替换父邮件,而合并则同时保留:父邮件和子邮件,使用合并或复制将从父邮件中删除邮件
您按照以下说明在父模型中编写它,并使用forms_errors_for:
validate do |parent|
errors.messages.clear
parent.children.each do |children|
next if children.valid?
errors.merge! children.errors
end
end
ActiveModel错误的定义
# Merges the errors from <tt>other</tt>.
#
# other - The ActiveModel::Errors instance.
#
# Examples
#
# person.errors.merge!(other)
def merge!(other)
@messages.merge!(other.messages) { |_, ary1, ary2| ary1 + ary2 }
@details.merge!(other.details) { |_, ary1, ary2| ary1 + ary2 }
end