block_given?在 erb 模板中总是 returns true
block_given? always returns true in erb templates
在 Rails 5.2.3 中,我需要渲染一个带有可选块的部分。
# users/_user.html.erb
...
<% if block_given? %>
<%= yield %>
<% else %>
<h1>Goodbye world</h1>
<% end %>
...
然而 block_given?
returns 无论我选择哪个版本,都是如此:
<%# 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" %>
这是怎么回事,为什么会这样?
因为所有 Rails 模板都支持 content_for :xyz
,这是由 yield :xyz
触发的,这意味着所有模板总是包装在一个准备获取此 [=13= 的块中]数据。
因为这个预编程块总是存在以适应 content_for
,这意味着 block_given?
将始终 return 为真。
我认为这实际上可能是 Rails 视图设计中的一个小疏忽。如果我们有一个单独的方法来检测部分是否提供了一个块,那就太好了。
一个解决方法:
<% if (block = yield).empty? %>
<h1>Goodbye world</h1>
<% else %>
<%= block %>
<% end %>
虽然很聪明而且是一个通用的解决方案,但我不喜欢 (block = yield).empty?
在那个特定实例中。
在我的用例和这个用例中,默认内容非常简单,我更喜欢这种方法:
<%= yield.presence || content_tag(:h1, "Goodby world") %>
在 Rails 5.2.3 中,我需要渲染一个带有可选块的部分。
# users/_user.html.erb
...
<% if block_given? %>
<%= yield %>
<% else %>
<h1>Goodbye world</h1>
<% end %>
...
然而 block_given?
returns 无论我选择哪个版本,都是如此:
<%# 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" %>
这是怎么回事,为什么会这样?
因为所有 Rails 模板都支持 content_for :xyz
,这是由 yield :xyz
触发的,这意味着所有模板总是包装在一个准备获取此 [=13= 的块中]数据。
因为这个预编程块总是存在以适应 content_for
,这意味着 block_given?
将始终 return 为真。
我认为这实际上可能是 Rails 视图设计中的一个小疏忽。如果我们有一个单独的方法来检测部分是否提供了一个块,那就太好了。
一个解决方法:
<% if (block = yield).empty? %>
<h1>Goodbye world</h1>
<% else %>
<%= block %>
<% end %>
虽然很聪明而且是一个通用的解决方案,但我不喜欢 (block = yield).empty?
在那个特定实例中。
在我的用例和这个用例中,默认内容非常简单,我更喜欢这种方法:
<%= yield.presence || content_tag(:h1, "Goodby world") %>