我有一个MediaItem模型,它有两个has_one
个关联。我使用以下方法验证其中一个是否存在:
validates_presence_of :photo, allow_nil: true
validates_presence_of :video, allow_nil: true
validate :photo_or_video_present
def photo_or_video_present
if !(photo.blank? ^ video.blank?)
errors['photo_attributes.image'] << 'Select a photo or a video'
errors['video_attributes.uid'] << 'Select a photo or a video'
end
end
在呈现表单时,它给出了以下错误对象:
<ActiveModel::Errors:0x007f99c8a71fc0
@base=#<MediaItem id: nil,
title: "asdadasdasd",
slug: "asdadasdasd",
gallery_id: 1,
created_at: nil,
updated_at: nil>,
@messages={:"photo_attributes.image"=>["Select a photo or a video"],
:"video_attributes.uid"=>["Select a photo or a video"],
:title=>[] }>
然而,这些错误并未出现在嵌套模型中。表格如下:
<div class="FormWrapper">
<%= simple_form_for [:admin, @gallery, @media_item], html: { class: "#{action_name.titleize}PhotoForm" } do |f| %>
<%= f.input :title %>
<div class="PhotoInputs">
<h3>Photo</h3>
<%= f.simple_fields_for :photo do |ff| %>
<%= ff.input :image, as: :file_upload, input_html: {preview: @media_item.photo.image} %>
<% end %>
</div>
<div class="VideoInputs">
<h3>Video</h3>
<%= f.simple_fields_for :video do |ff| %>
<%= ff.input :provider, as: :radio_buttons, collection: Video::PROVIDERS %>
<%= ff.input :uid %>
<% end %>
</div>
<hr>
<%= render partial: 'shared/form_submit', locals: {resource: @media_item} %>
<% end %>
</div>
为什么这些内联错误无法显示?
注意:表单的功能绝对没有问题。我可以毫无问题地创建和编辑模型和嵌套模型。
答案 0 :(得分:1)
这两个验证不执行任何操作validates_presence_of :photo, allow_nil: true
validates_presence_of :video, allow_nil: true
,因为您正在验证存在但允许它不存在。我只需将error
添加到:base
并在视图中渲染它。 e.g。
validates :has_photo_or_video
def has_photo_or_video
if (photo.blank? ^ video.blank?)
errors.add(:base,"Please select a photo or video")
end
end
然后在视图中
<% f.errors[:base].each do |message| %>
<span>message</span>
<% end %>
我没有看到像你描述的内联错误的实现,尽管你也可以尝试这样的事情:
def has_photo_or_video
if !(photo.blank? ^ video.blank?)
photo.errors.add(:image,"Please select a photo or video")
video.errors.add(:uid,"Please select a photo or video")
end
end
虽然我没有说明这是否有效。
您的问题是它正在寻找包含在嵌套哈希中的错误,例如
{photo_attributes: {image: ["Please select a photo or video"]},
video_attributes: {uid: ["Please select a photo or video"]} }
我看到这样做的唯一方法是通过验证相关模型,这在您的情况下是不可能的,因为它是一个或两个类型的过程。至少我理解它。
如果这是一个或类型的过程,意味着MediaItem
是Photo
或一个Video
,而不是两者那么我建议研究多态性,因为它会使这个过程变得容易。
或者甚至更好地废弃MediaItem
所有内容并将title
属性添加到Photo
和Video
,然后分别创建每个属性,因为这似乎是最简单的路线。 (您仍然可以为media_items
定义一个可以获取所有这些的方法