0

次のような構文を許可するビュー ヘルパーをレールで作成したいと考えています。

<%= 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それに対処する方法について途方に暮れています。

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 に答える