我有一个包含两个块的ERB视图:
<%= test_h1 do %>
<%= 'test1' %>
<% end -%>
<%= test_h2 do %>
<%= 'test2' %>
<% end -%>
其中test_h1
和test_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
的惯用方式是什么?
答案 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 -%>
答案 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