捕获 Rails 视图块时出现差异

Discrepancy when capturing Rails view block

我有一个包含两个块的 ERB 视图:

<%= test_h1 do %>
  <%= 'test1' %>
<% end -%>

<%= test_h2 do %>
  <%= 'test2' %>
<% end -%>

其中 test_h1test_h2 是相似的助手,但一个是在助手文件中定义的,而另一个是通过 helper_method 在控制器中定义的:

module TestHelper
  def test_h1(&block)
    link_to '/url' do
      capture(&block)
    end
  end
end

class TestController < ApplicationController
  helper_method :test_h2

  def test_h2(&block)
    helpers.link_to '/url' do
      helpers.capture(&block)
    end
  end
end

test_h1 产生预期结果,test_h2 首先呈现内部模板块:

<a href="/url">test1</a>

test2<a href="/url"></a>

为什么? test_h2 的惯用写法是什么?

我认为两个视图示例都应该重写为:

<%= test_h1 do %>
  <% 'test1' %>
<% end -%>

<%= test_h2 do %>
  <% 'test2' %>
<% end -%>

我的理解是“<%=”强制将块的输出渲染到输出流,这不是这两个示例中的预期行为

在 rails 中采用的惯用方法是将 test_h2 方法移动到一个关注点,并将该关注点包含在控制器和助手 class 中。

或者在您的控制器 class.

中将 test_h2 定义为 helper_method 但通常在多个地方需要的方法应该放在关注点中,并在需要的地方包括这些关注点。

此外,如果您需要视图的方法,请在帮助程序中包含关注点或定义您自己的方法。

参考 Can we call a Controller's method from a view (as we call from helper ideally)?
How to use concerns in Rails 4

当从你的控制器使用 capture 时,输出被附加到页面缓冲区,因此你的 erb 的 <%= 立即输出到页面输出。

要解决此问题,您需要在 test_h2 块中使用 <%。因此,要在这两种情况下都获得预期的行为,请使用以下语法:

<%= test_h1 do %>
  <%= 'test1' %>
<% end -%>

<%= test_h2 do %>
  <% 'test2' %>
<% end -%>

本文中的更多信息:https://thepugautomatic.com/2013/06/helpers/

capture 覆盖当前输出缓冲区并只调用块(仍然绑定到其他视图上下文),因此从控制器调用时覆盖无效,因为 view_context 不是相同的上下文正在渲染视图。

要解决上下文,您可以像这样定义您的助手:

# in controller
helper do
  def test_h3(&block)
    # this will run in view context, so call `controller.some_func` to access controller instance
    link_to '/url' do
      capture(&block)
    end
  end
end