捕获Rails视图块时的差异

时间:2018-12-14 10:43:03

标签: ruby-on-rails ruby-on-rails-5 actionview

我有一个包含两个块的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的惯用方式是什么?

4 个答案:

答案 0 :(得分:3)

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

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

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

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

答案 1 :(得分:2)

从控制器使用capture时,输出将附加到页面缓冲区,结果,来自erb的<%=将立即输出到页面输出。

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

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

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

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

答案 2 :(得分: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

答案 3 :(得分:-1)

在rails中实现的理想方式是将test_h2方法移至关注点,并将该关注点包含在控制器以及帮助器类中。

否则,在控制器类中将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