如何在函数中重用 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_datetime
和 time_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
中很容易做到 :-)。
我在 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_datetime
和 time_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
中很容易做到 :-)。