当辅助方法使用yield关键字时,Rails部分模板会重复渲染

发布于 2024-10-02 21:45:54 字数 1574 浏览 5 评论 0原文

当使用带有部分布局的 Rails 以及使用 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)。我已经确定它是 my_iterator 与 Rails 部分模板机制的结合的产量。如果我按如下方式编写 my_iterator ,输出将如我所料。 (我还需要更改我的部分模板来执行 my_iterator.each)

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

有没有一种方法可以对此进行编码,这样我就不会与 Rails 发生冲突并获得重复渲染,但仍然可以使用 Yield 将辅助方法编码为迭代器?另外,有人可以准确解释重复渲染是如何发生的吗?

I have seen some strange behavior when using rails with partial layouts plus a helper method coded as an iterator using the yield keyword. I am hoping someone can:

  1. Explain what's going on and why I get the duplicate rendering and maybe
  2. Suggest an alternate approach, hopefully other than just re-coding my helper method to be a simple function that returns a list (I've already done that as an interim workaround)

So if I create the following 3 things in my rails 3 app, I get unexpected output.

[UPDATE]
I have tested the following combinations:

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)

So maybe it's an erb vs. haml thing, but when I initially discovered this it was on haml templates. Hmmm....anyone know what's going on???

A) A main template that looks like this (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) A helper method like this (app/helpers/main_helper.rb)

  module MainHelper

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

C) A partial template like this (app/views/main/_partial.html.erb)

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

When I view the result in the browser, I see the "iterator running with" block a total of 8 times (1 2 3 4 1 2 3 4). I have determined it is the yield within my_iterator screwing with the rails partial template mechanism. If I code my_iterator as follows, the output is as I would expect. (I also need to change my partial template to do my_iterator.each)

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

Is there a way to code this such that I don't screw with rails and get duplicate rendering but can still code a helper method as an iterator using yield? Also, can someone explain exactly how the duplicate rendering happens?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

初见 2024-10-09 21:45:54

我刚刚遇到了一个非常相似的问题,并且设法解决了它。我相信如果重写上面的原始帮助器,它会按预期工作...

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() ,重复的渲染就会消失。

I was just having a very similar issue and just managed to solve it. I believe the original helper above would work as expected if rewritten it as such...

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

The same problem seems to occur in Rails 3 if your calling concat(capture(&block)) or concat(block.call). In both cases, just drop the concat() and the duplicate rendering vanishes.

提笔落墨 2024-10-09 21:45:54

我遇到了类似的问题,该问题只出现在生产中,而不是开发中。我将其范围缩小到

    config.action_view.cache_template_loading = true

我的development.rb。当设置为 true 时,我在 haml 文件中看到了一个元素。 违规代码的范围

    = if @user.bio
      = @user.bio

通过添加和删除块,我缩小了导致重新打印之前的整个块的 。只需将 = 替换为 - 即可解决此问题。调试起来很尴尬,因为我必须在生产模式下进行调试。

我的建议是寻找逻辑运算符上错误的 = 输出。

    - if @user.bio
      = @user.bio

I was experiencing a similar problem which only appeared in production, not development. I narrowed this down to

    config.action_view.cache_template_loading = true

in my development.rb. When set to true, I saw a elements in my haml file. By adding and removing blocks I narrowed down the offending code to

    = if @user.bio
      = @user.bio

which was causing the entire block which preceded this to be re-printed. Simply replacing = with - solves this. It was awkward to debug simply because I had to do in debug in production mode.

My advice is to look for errant = outputs on logical operators.

    - if @user.bio
      = @user.bio
穿越时光隧道 2024-10-09 21:45:54

在助手中使用 content_for 将在每次迭代中附加内容。您可以编写一个 ApplicationHelper 方法来在帮助程序中生成内容,如下所示:

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

然后在其他帮助程序文件中使用 Yield_content 而不是 content_for 。

Using content_for within a helper will append content on each iteration. You can write a ApplicationHelper method to yield content within helpers like so:

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

Then use yield_content instead of content_for within your other helper files.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文