0

我想在 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>'s 完全丢失,'s 的块内容甚至<td>不在<tbody>标签内。

我在 StackOverflow 上发现了这个问题:Loop & output content_tags within content_tag in helper并尝试使用,concat但是我收到以下错误:

undefined method `concat'

我猜这与丢失的上下文有关,.each但我不知道如何解决它。

4

1 回答 1

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类上实现功能时它变得不可见。

于 2012-11-29T00:31:41.233 回答