我想在rails中创建一个视图助手,它允许使用如下语法:
<%= some_fancy_list @items do |h| %>
<%= h.rows :class => "whatever" |item| %>
<td><= item.id %>
<% end %>
<% end %>
我已经构建了这个(这是一个简化版本)
的效果def some_fancy_list(items, &block)
h = InternalHelper.new(:items => items)
content_tag(:table) { block.call(h) }
end
class InternalHelper
include ActionView::Helpers::TagHelper
include ActionView::Context
def initialize
...
end
def rows(options = {}, &block)
content_tag(:tbody) do
@items.each do |item|
content_tag(:tr, options) do
block.call(item) if block_given?
end
end
end
end
end
问题是它输出的HTML并不完全符合我的预期。
<table>
<td>1</td>
<td>2</td>
<td>3</td>
<tbody></tbody>
</table>
<tr>
完全丢失,<td>
的阻止内容甚至不在<tbody>
标记内。
我在StackOverflow上发现了这个问题:Loop & output content_tags within content_tag in helper并尝试使用concat
但是我收到以下错误:
undefined method `concat'
我猜这与.each
中丢失的上下文有关,但我对如何处理它感到茫然。
答案 0 :(得分:0)
问题似乎在于使用了最初调用视图助手的上下文之外的另一个类。解决方案包括删除Content和TextHelper的包含,然后在类上创建一个代理方法,该方法链接回调用该类的上下文。
# self is passed into the helper class:
h = InternalHelper.new(self, :items => items)
# then the helper class makes a proxy back to that parent instance
class InternalHelper
# removed these:
# include ActionView::Helpers::TagHelper
# include ActionView::Context
# added this:
def content_tag(*args, &block)
@parent.content_tag(*args, &block)
end
end
这基本上使得content_tag
从相同的上下文中调用,就好像它在视图助手中一样,并且它以在InternalHelper
上实现功能时变得不可见的方式来实现类。