如何在函数中重用 ERB 模板代码?

How to reuse ERB templating code in function?

我在 ERB 模板中有这段代码来呈现列表中的所有文章。

    <% @list.each do |a| %>
    <article class="my-panel">
      <header>
        <h2><a href="<%= rel_url_to a[:rel_url] %>"><%= a[:name] %></a></h2>
         <time datetime="<%= to_datetime(a[:time]) %>"><%= time_description(a[:time]) %></time>
      </header>
       ... more stuff cut out
    </article>
    <% end %>

现在我要把它改成这样:

<% @list[content_splitter.before_ad_range].each  do |a| %>
   <%= render_article(a) %>
<% end %>

<%= AdCreator.between_content_ad %>

<% @list[content_splitter.after_ad_range].each do |a| %>
   <%= render_article(a) %>
<% end %>

我认为在模板中定义 render_article 会更好,而不是让 html 弄乱我的 ruby 代码。但是当我将该代码移动到函数内部时,我得到了一个错误。

这是函数:

  <% def render_article(a) %>
    <article class="my-panel">
      <header>
        <h2><a href="<%= rel_url_to a[:rel_url] %>"><%= a[:name] %></a></h2>
         <time datetime="<%= to_datetime(a[:time]) %>"><%= time_description(a[:time]) %></time>
      </header>

      <div class="image">
        <a href="<%= rel_url_to a[:rel_url] %>"><img alt="" src="<%= rel_url_to a[:img_url_1x] %>" srcset="<%= rel_url_to a[:img_url_2x] %> 2x, <%= rel_url_to a[:img_url_3x] %> 3x"></a>
      </div>

      <div class="text">
        <%= a[:article_text] %>
      </div>
    </article>
  <% end %>

这是错误:

undefined local variable or method `_erbout' for #<Html::FrontPage:0x0055fb94005c68>

产生此错误的代码行是:

self.class.instance_variable_get(:@renderer).result(binding)

为什么会这样?如何找到更多信息错误?

如何解决这个问题?我可以避免将这个明显 html 显性代码移动到 ruby 辅助文件中吗?

PS。我怀疑问题是无法从 ERB 函数内部访问函数 to_datetimetime_description

我知道函数 render_article 确实被调用了,因为如果我更改它的签名以删除参数,我会得到一个错误

wrong number of arguments (given 1, expected 0)
# (erb):45:in `render_article'

您尝试做的事情在技术上并非不可能,而是相当困难且不推荐,阅读 this question.

的评论和答案可以看出这一点

正如您的错误消息指出的那样,您的 def 不会在您 "probably" 期望的上下文中完全发生,并且您在定义方法时肯定无法 "freely use erb features" (因为你的上下文和你期望的完全不同)。

"railsy" 方法是添加助手或使用 partial,但两者都有其缺点。 .erb 文件(作为大多数模板语言)不 "factor" 好。如果您想更自由地分解事物,您应该查看 fortitude gem,它提供了基本上是 html 的 ruby-DSL,这很容易分解。但是,与您可能习惯的情况相比,这是一个相当大的变化。

如果您真的想在.erb文件中定义一个方法,那么您必须完全在一对<% ... %>中完成括号中您将访问您的参数,您的上下文。您必须 return 基本上是 String 才能在 <%= ... %> 中使用它,并且非常注意转义规则以使其通过.这很可能比它的价值更麻烦(但在 fortitude 中很容易做到 :-)。