2

部分的なレイアウトと、yield キーワードを使用してイテレータとしてコード化されたヘルパー メソッドをレールで使用すると、奇妙な動作が見られます。私は誰かができることを願っています:

  1. 何が起こっているのか、なぜレンダリングが重複するのかを説明してください。
  2. うまくいけば、リストを返す単純な関数になるようにヘルパー メソッドを再コーディングする以外に、別のアプローチを提案します (暫定的な回避策として既に実行しています)。

したがって、Rails 3 アプリで次の 3 つを作成すると、予期しない出力が得られます。

[更新] 次の組み合わせをテストしました。

Rails 3.0.0 + erb (has this issue)
Rails 3.0.0 + haml (OK)
Rails 3.0.3 + erb (has this issue)
Rails 3.0.3 + haml (OK)

erb と haml の問題かもしれませんが、最初にこれを発見したときは haml テンプレートでした。うーん....何が起こっているのか知っている人はいますか?

A) このようなメイン テンプレート (app/views/main/index.html.erb)

  <h1>Main#index</h1>
  <p>This is content from main#index before the partial template rendering
  <%= render :partial => "partial" %>
  <p>This is content from main#index after the partial template rendering.</p>

B) このようなヘルパー メソッド (app/helpers/main_helper.rb)

  module MainHelper

    def my_iterator
      yield 1
      yield 2
      yield 3
      yield 4
    end
  end

C) このような部分テンプレート (app/views/main/_partial.html.erb)

  <% my_iterator do |x| %>
  <p>iterator running with <%= x %></p>
  <% end %>

ブラウザーで結果を表示すると、「iterator running with」ブロックが合計 8 回表示されます (1 2 3 4 1 2 3 4)。Railsの部分的なテンプレートメカニズムをねじ込む my_iterator 内の歩留まりであると判断しました。my_iterator を次のようにコーディングすると、出力は期待どおりになります。(my_iterator.each を実行するように部分テンプレートを変更する必要もあります)

def my_iterator
  logger.debug("my_iterator called")
  return [1, 2, 3, 4]
end

これをコーディングして、レールを台無しにしてレンダリングを重複させずに、yield を使用してイテレータとしてヘルパー メソッドをコーディングできるようにする方法はありますか? また、重複したレンダリングがどのように発生するかを誰かが正確に説明できますか?

4

3 に答える 3

3

私は非常によく似た問題を抱えていて、それを解決することができました。上記の元のヘルパーは、そのように書き直せば期待どおりに機能すると思います...

module MainHelper
  def my_iterator(&block)
    block.call(1)
    block.call(2)
    block.call(3)
    block.call(4)
  end
end

concat(capture(&block))またはを呼び出すと、Rails 3 でも同じ問題が発生するようconcat(block.call)です。どちらの場合も、 をドロップするだけconcat()で、重複したレンダリングは消えます。

于 2011-06-22T21:18:06.810 に答える
1

開発ではなく、本番環境でのみ発生する同様の問題が発生していました。これに絞りました

    config.action_view.cache_template_loading = true

私のdevelopment.rbで。true に設定すると、haml ファイルに要素が表示されました。ブロックを追加および削除することで、問題のあるコードを絞り込みました

    = if @user.bio
      = @user.bio

これにより、これに先行するブロック全体が再印刷されていました。= を - に置き換えるだけで解決します。本番モードでデバッグしなければならなかったので、デバッグするのは面倒でした。

私のアドバイスは、論理演算子で間違った = 出力を探すことです。

    - if @user.bio
      = @user.bio
于 2011-09-13T19:39:11.103 に答える
0

ヘルパー内で content_for を使用すると、反復ごとにコンテンツが追加されます。次のように、ヘルパー内にコンテンツを生成する ApplicationHelper メソッドを記述できます。

def yield_content(content_key)
  view_flow.content.delete(content_key)
end

次に、他のヘルパー ファイル内で content_for の代わりに yield_content を使用します。

于 2012-11-13T22:30:54.397 に答える