为什么Aren这些错误渲染嵌套关联?

时间:2014-10-28 17:00:36

标签: ruby-on-rails ruby forms ruby-on-rails-4 simple-form

我有一个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>

为什么这些内联错误无法显示?

注意:表单的功能绝对没有问题。我可以毫无问题地创建和编辑模型和嵌套模型。

1 个答案:

答案 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"]} }

我看到这样做的唯一方法是通过验证相关模型,这在您的情况下是不可能的,因为它是一个或两个类型的过程。至少我理解它。

如果这是一个或类型的过程,意味着MediaItemPhoto 一个Video,而不是两者那么我建议研究多态性,因为它会使这个过程变得容易。

或者甚至更好地废弃MediaItem所有内容并将title属性添加到PhotoVideo,然后分别创建每个属性,因为这似乎是最简单的路线。 (您仍然可以为media_items定义一个可以获取所有这些的方法