块给定?在 erb 模板中总是返回 true

Posted

技术标签:

【中文标题】块给定?在 erb 模板中总是返回 true【英文标题】:block_given? always returns true in erb templates 【发布时间】:2020-02-19 00:04:36 【问题描述】:

在 Rails 5.2.3 中,我需要渲染一个带有可选块的部分。

# users/_user.html.erb
...
<% if block_given? %>
  <%= yield %>
<% else %>
  <h1>Goodbye world</h1>
<% end %>
...

但是,无论我选择使用哪个版本,block_given? 都会返回 true:


<%# Version 1 - block_given? returns true %>
<%= render partial: "users/_user" do %>
  <h1>hello world</h1>
<% end %>

<%# Version 2 - block_given? also returns true %>
<%= render partial: "users/_user" %>

这是怎么回事?为什么会这样?

【问题讨论】:

【参考方案1】:

因为所有 Rails 模板都支持content_for :xyz,这是由yield :xyz 触发的,这意味着所有模板总是包装在一个准备获取此content_for 数据的块中。

因为这个预编程块始终存在以容纳content_for,这意味着block_given? 将始终返回true。

我认为这实际上可能是 Rails 视图设计中的一个小疏忽。如果我们有一个单独的方法来检测一个部分是否提供了一个块,那就太好了。

解决方法的一个想法:

<% if (block = yield).empty? %>
  <h1>Goodbye world</h1>
<% else %>
  <%= block %>
<% end %>

【讨论】:

很好的答案!谢谢。【参考方案2】:

虽然我很聪明并且是通用的解决方案,但在那个特定的情况下,我不喜欢 (block = yield).empty?

在我的用例和这个默认内容非常简单的情况下,我更喜欢这种方法:

<%= yield.presence || content_tag(:h1, "Goodby world") %>

【讨论】:

以上是关于块给定?在 erb 模板中总是返回 true的主要内容,如果未能解决你的问题,请参考以下文章

erb模板中的一条评论如何?

在 Rails 3 中处理 JS/ERB 模板中的 JSON

是否可以在 erb 模板中要求一个类?

如何在rails中提供erb文件作为蛋白石模板?

哪种 Java HTML 模板技术的工作方式最接近 Ruby (erb/haml)?

从数据库呈现erb的最佳方法?