使用.exists?在 Rails 视图中

Using .exists? in Rails view

我正在开发 Rails 应用程序,该应用程序使用以下方法在特定位置呈现签名:

 <div id="signature" style='position: absolute; left: <%= @document.template.signature_position.left %>px; top: <%= @document.template.signature_position.top %>px; '>

问题是,如果用户没有为模板设置 signature_position 然后尝试打开显示视图,他们将收到 @document.template.signature_position.left 为 nil 的错误。

如果 @document.template.signature_position.left 不存在,则预期的操作是完全忽略签名 div 并呈现页面的其余部分。我尝试按照以下方式使用各种解决方案:

`<%= if document.template.signature_position.left.exists?  %>
     <div id="signature" style='position: absolute; left: <%= @document.template.signature_position.left %>px; top: <%= @document.template.signature_position.top %>px; '>
     ..... extraneous functioning code  .....
<% end %>`

但我显然使用了不正确的语法,因为无论我如何更改,我都会遇到各种错误,主要是“期待 keyword_then 或 ';'”或 '\n'"。

Furious Googling 带来了一些有趣的阅读,但到目前为止没有任何用处。有人可以通过建议预期操作的正确语法来提供帮助吗?

你的语法有点不对劲。

<%= 插入表达式的值,但您只想计算条件,所以 <% 就足够了:

<% if document.template.signature_position.left.exists? %>
   ... code
<% end %>

你的条件语句中也有一个不必要的 ?(我从上面的例子中删除了)。

我很难想出 "official" ERB 语法的文档,但 Puppet Labs 有一个很好的指南 here

根据@nick 和@cthulhu 的建议,我想出了一些创建所需功能的解决方法:

<% if @document.template.signature_position.nil? %>
    <div></div>
<% else %>
     <div id="signature" style='position: absolute; left: <%= @document.template.signature_position.left %>px; top: <%= @document.template.signature_position.top %>px; '>
.... code ....
<% end %>

几件事:

  • ActiveRecord::FinderMethods#exists? 用于检查数据库中的记录,因此这是您将在控制器中而不是在视图中使用的方法。
  • 您更有可能希望使用 Object#present?(例如 @document.template.signature_position.left.present?)在您的视图中有条件地呈现某些代码
  • 您正在根据 @document.template.signature_position.left 的结果调用 @document.template.signature_position.top。您确定不需要先检查这两个值是否都存在吗?
  • 您的视图对 @document 对象的深度遍历了解很多,例如它有一个 template,一个 signature_position,一个 left 属性。为了与 Law of Demeter 保持一致,这些知识可以从您的视图中清除并进一步推入堆栈。

这是我对第一轮代码重构的看法(做出一些假设):

在您的模型中:

class Document < AR::Base
  def left_signature_position
    template.signature_position&.left
  end

  def top_signature_position
    template.signature_position&.top
  end

  def show_signature?
    left_signature_position.present? && 
      top_signature_position.present?
  end
end

那么,在你看来:

<% if @document.show_signature? %>
  <div id="signature" style='position: absolute; left: <%= @document.left_signature_position %>px; top: <%= @document.top_signature_position %>px; '>
<% end %>

其他进一步的重构可能包括将生成签名标记的代码放入辅助方法,and/or 为您的 template 添加委托、装饰器 and/or 辅助方法和 signature_position 类 清理模型中现在的 template.signature_position&.top 风格的方法。