gpt4 book ai didi

ruby-on-rails - 回滚 : what are the benefits of erb in Rails code?

转载 作者:行者123 更新时间:2023-12-04 06:15:19 24 4
gpt4 key购买 nike

我读了 Magnus Holm 的一篇题为 Block Helpers in Rails 3 的帖子。 ,其中他指出 Rails 3 过度弯曲 ERB 的语法。 (在“原始”ERB 中,ERB 构造只能跨越单个语句。Rails 3 允许 - 甚至需要 - 跨越多个语句。)

这让我想知道:与 Ruby 的原生字符串处理相比,使用 ERB 的真正优势是什么?为了深入研究这一点,我采用了 ERB 文档中列出的示例,并在 ERB 和原生 Ruby 字符串中进行了尝试。事实证明,Ruby 丰富的字符串处理库使翻译变得非常简单——甚至是直观的。

这是它的外观。两者的共同点(直接从 ERB 文档中提取):

require "erb"

# Build template data class.
class Product
def initialize( code, name, desc, cost )
@code = code
@name = name
@desc = desc
@cost = cost
@features = [ ]
end

def add_feature( feature )
@features << feature
end

# Support templating of member data.
def get_binding
binding
end
end

这是用 ERB 编写的模板和扩展:
# ================================================================
# using ERB
erb_template = %{
<html>
<head><title>Ruby Toys -- <%= @name %></title></head>
<body>
<h1><%= @name %> (<%= @code %>)</h1>
<p><%= @desc %></p>
<ul>
<% @features.each do |f| %>
<li><b><%= f %></b></li>
<% end %>
</ul>
<p>
<% if @cost < 10 %>
<b>Only <%= @cost %>!!!</b>
<% else %>
Call for a price, today!
<% end %>
</p>
</body>
</html>
}.gsub(/^ /, '')
rhtml = ERB.new(erb_template)
# Produce results
@r1 = rhtml.result(toy.get_binding)

这是用纯 Ruby 编写的模板:
# ================================================================
# using native Ruby strings
ruby_template = %q{"
<html>
<head><title>Ruby Toys -- #{ @name }</title></head>
<body>
<h1>#{ @name } (#{ @code })</h1>
<p>#{ @desc }</p>
<ul>
#{ @features.map do |f|
"<li><b>#{f}</b></li>\n"
end.join }
</ul>
<p>
#{ if @cost < 10
"<b>Only #{ @cost }!!!</b>"
else
"Call for a price, today!"
end
}
</p>
</body>
</html>
"}
# Produce results
@r2 = eval(ruby_template, toy.get_binding)

这些产生相同的结果(模空白)。 ERB 是更简单还是更难,真的是品味和经验的问题。从关于 ERB 和 <%= ... %> vs <% ... %> vs <%= ... -%> 的问题数量来看,似乎很多人可能更容易坚持纯 Ruby .

冒着引发某种圣战的风险,当原生 Ruby 做同样的工作时,为什么还要为 ERB 烦恼呢?你觉得ERB有用吗? Rails 是否也应该接受“原生 Ruby”模板?

最佳答案

马格努斯霍尔姆在这里;很高兴看到你喜欢这篇文章:-)

首先让我们看一下模板(是的,插值是一个模板)作为使用常规代码构造字符串的演变:

# "Regular" way of constructing a string:
str = "Hello World: "
@users.each do |user|
str << "How are you today, "
str << user.name
str << "? \n"
end

如果我们看一下这段代码,很明显有三种模式在重复:
  • 我们有大量附加的静态文本:str << "Static"
  • 我们有一些附加的动态代码:str << expresstion
  • 我们有一些代码块可以改变控制流:@users.each

  • ERB 的伟大之处在于它是这些模式的完美同构,这意味着用户可以按照常规方式构造字符串来考虑它。这只是一种构造字符串的方法,它更关注静态部分(因为它们很常见)而不是动态部分。

    作为“纯粹主义者”,您已经注意到这不是最低级别。这是完全正确的:只要您可以评估图灵完备的代码,您的模板引擎就成为图灵完备的,从技术上讲,您不需要任何其他东西。当您可以简单地嵌套模板引擎时,您不需要 block 。

    现在我们需要考虑一下低级和易于理解之间的区别。是的,当你移除建筑部件时,你最终会得到一个更小的核心,但这并不一定会让它更容易理解。您可以对 GOTO 进行类比:您可以使用一个单一概念 (GOTO) 创建任何循环/条件,但事实证明,使用 if/while 语句来推理代码更容易。为什么?因为出现了花纹!不是每次我们查看这些模式时都在概念上解析它们,而是更容易创建我们可以立即理解的抽象。

    在您的示例中,我相信任何模板都会使用一种模式: @users.map { |f| code }.join .这正是 ERB 试图抽象出来的东西,因此您可以忘记有关逻辑的细节和原因。

    我还相信,如果您要使模板引擎更简单,但仍使其图灵完备,那么无论如何您都会抽象出这些细节。您将意识到出现了一种模式,并且作为 DRY 编码器,您将开始创建助手等。您实际上是在另一个之上实现自己的小模板引擎。现在一切都取决于基础语言的语法灵 active ,无论您是否设法在没有太多其他噪音的情况下抽象出真实的细节。例如,有一些支持静态类型和模式匹配的 Lisp 风格,但通常它无法击败专门为该问题设计的语法。

    那么,与 Ruby 的原生字符串处理相比,使用 ERB 的真正优势是什么?一句话: 它为常见模式提供了很好的语法。

    Do you think ERB is useful?



    是和不是。我认为插值绝对不是正确的方法。您将在模板中看到模式,在模板方面没有什么比自定义语法更好的了。我认为 ERB 还是挺有用的,但是它在某些方面有所欠缺:它没有 block 也是表达式的概念:
    # This block is more like a statement (we don't care about the return value)
    @users.each do |foo|
    str << "Hello"
    end

    # This block is an expression
    str << form_for(thing) do
    another_string
    end

    我不知道你是否可以用语法来解决这个问题,但是现在它在每个框架中都是“固定的”,并且没有办法编写跨多个框架工作的 block 助手。我很想看到一种更“官方”的方式来处理这个问题。

    Should Rails accept "native Ruby" templates as well?



    Tilt已经这样做了,最好的解决方案是如果 Rails 切换到 Tilt,但我认为“原生 Ruby”毕竟没有那么有用。如果它是一个简短的模板,你当然可以在你的代码中直接使用一个插值字符串。如果它是一个大模板,并且您要将它从 Ruby 文件中移出,为什么不使用为模板设计的语法呢?

    关于ruby-on-rails - 回滚 : what are the benefits of erb in Rails code?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5172372/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com