7

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

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

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

wheretest_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

4

4 回答 4

3

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

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

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

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

于 2018-12-14T20:52:19.823 回答
2

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

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

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

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

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

于 2018-12-17T19:17:36.963 回答
2

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
于 2018-12-21T12:16:55.313 回答
-1

在 Rails 中执行此操作的惯用方法是将 test_h2 方法移至关注点,并将该关注点包含在控制器和帮助器类中。

或者在你的控制器类中将 test_h2 定义为 helper_method。

但一般来说,在多个地方需要的方法应该放在关注点中,并在需要的地方包含这些关注点。

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

参考我们可以从视图中调用控制器的方法吗(理想情况下我们从助手调用)?
如何在 Rails 4 中使用关注点

于 2018-12-16T14:27:51.930 回答