You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

修复Ruby Blacklight视图rdf.fedora.hasPart为空时UI显示异常

问题根因

报错是典型的Ruby空值调用方法异常:当Solr返回的文档没有rdf.fedora.hasPart字段时,@document["rdf.fedora.hasPart"]会返回nil,直接对nil调用each会抛出NoMethodError;就算字段存在,如果值是空字符串、数字这类非可枚举类型,一样会触发页面渲染失败。

解决方案

在ERB视图层遍历前增加值合法性校验即可,有两种常用实现,可根据自己的编码习惯选择:

方案1:前置判断(可读性强,适合新手)

在执行循环前先判断字段存在、值为可遍历的非空集合,满足条件才渲染循环内的内容,修改后的ORAL HISTORY区块代码如下:

<!-- ORAL HISTORY  -->
<% elsif document.id =~/oh/ %>

 <iframe src="/pdfjs/web/viewer.html?file=%2Fdocpdfview%2F<%=@document.id%>" allowfullscreen webkitallowfullscreen style="width: 100%; height: 640px"></iframe>
  <button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">Download</button>
  <div class="dropdown-menu">
    <a class="dropdown-item" target="_blank" href="/pdfdownload/<%=@document.id%>">PDF</a>
    <a class="dropdown-item" target="_blank" href="/txt/<%=@document.id%>">Plain Text</a>
    <a class="dropdown-item" target="_blank" href="/dc/<%=@document.id%>">Metadata (Dublin Core)</a>
  </div>

  <video id="videoarea" controls="controls" poster="" src=""></video>
  <%# 提前把字段值存到局部变量,避免重复从Solr文档取值 %>
  <% has_part_items = @document["rdf.fedora.hasPart"] %>
  <%# 校验值为数组类型且非空才执行遍历 %>
  <% if has_part_items.is_a?(Array) && has_part_items.any? %>
    <% has_part_items.each do |item| %>
      <ul class="playlist">
        <li movieurl="/mp3/<%=item%>"><%=item%></li>
      </ul>
    <% end %>
    <br><br>

    <% has_part_items.each do |item| %>
      <%=item%>
      <div class="preview_image" align="left">
        <video class="video-js vjs-fluid vjs-default-skin"
          controls=""
          data-setup='{ "aspectRatio":"640:120"}'
          playsinline=""
          poster="/pageturnerserver/ajaxp?theurl=http://localhost:8080/fedora/get/<%=@document.id%>/Preview"
          preload="none">
          <source
            src="/mp3/<%=item%>"
            type="video/mp4">
        </video>
      </div>
    <% end %>
  <% end %>

<!-- AUDIO  -->
<% elsif document.id =~/aud/ %>
  <div class="preview_image" align="left">
    <video class="video-js vjs-fluid vjs-default-skin"
      controls=""
      data-setup='{ "aspectRatio":"640:120"}'
      playsinline=""
      poster="/pageturnerserver/ajaxp?theurl=http://localhost:8080/fedora/get/<%=@document.id%>/Preview"
      preload="none">
      <source src="/mp3/<%=@document.id%>" type="video/mp4">
    </video>
  </div>

校验逻辑做了两层防护:

  • 先判断值是Array类型:Solr多值字段默认返回数组格式,这层可以避免字段存了字符串、数字等非可枚举值时触发报错
  • 再用any?判断数组非空:空数组遍历虽然不会报错,但会生成无意义的空DOM标签,加这层判断可以精简输出的HTML

方案2:安全遍历(代码更简洁)

如果不想写冗长的前置判断,可以直接用Ruby内置的Array()方法做兜底转换,一行就能兼容所有空值场景:

<%# Array()会自动把nil、非数组值转成合法数组,永远不会触发遍历报错 %>
<% Array(@document["rdf.fedora.hasPart"]).each do |item| %>
  <ul class="playlist">
    <li movieurl="/mp3/<%=item%>"><%=item%></li>
  </ul>
<% end %>

Array()是Ruby内核自带的类型转换方法:传入nil时返回空数组,传入数组时直接返回原数组,传入单值时自动把单值包装成单元素数组,完全覆盖Solr字段可能返回的所有值类型。

额外优化提示
  • 现有代码两次遍历同一个rdf.fedora.hasPart字段,可以合并成一次循环,减少重复逻辑
  • HTML规范要求id属性全局唯一,循环内给每个ul加id="playlist"会生成重复ID,建议改成class属性

内容的提问来源于stack exchange,提问作者Calvin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:24:10