在 HAML 中映射集合时显示的嵌套

Nesting displayed when mapping collection in HAML

我正在使用 HAML 开发 Rails 应用程序。当我偶然发现这种奇怪的行为时,我需要向用户展示一个列表:

这段代码显然没有输出。

- 5.times.map do |n|
  - n + 1

此代码生成 1 2 3 4 5,因为它为内部语句输出 return 值。

- 5.times.map do |n|
  = n + 1                # Notice the =

此代码生成 [1, 2, 3, 4, 5],因为它正在输出映射数组。

= 5.times.map do |n|     # Notice the =
  - n + 1

到目前为止,还不错...

此代码生成 1 2 3 4 5 [0, 0, 0, 0, 0],因为它不喜欢人类。

= 5.times.map do |n|     # Notice the =
  = n + 1                # on both lines

此代码生成 1 2 3 4 5 [1, 1, 1, 1, 1],因为它嵌套在 <p>.

%p                       # Here we are nested one <p> deep
  = 5.times.map do |n|
    = n + 1

此代码生成 1 2 3 4 5 [2, 2, 2, 2, 2],因为它是双重嵌套的(依此类推)。

%p                       # Here we are nested two <p> deep
  %p
    = 5.times.map do |n|
      = n + 1

有人对 HAML 内部发生的事情有解释吗? = n+1 是否都将字符串添加到某个输出缓冲区,然后 return 进入它的嵌套级别?

实际上,您所问的是非常依赖于版本的。我的意思是它将在即将推出的 Haml 版本中产生不同的结果 (v4.1.0)。

但首先让我们找出为什么这个输出版本 < 4.1.0?

在幕后,Haml 将模板转换为可执行 Ruby 代码。这项工作在 Haml::Compiler class 中完成,您可以轻松调试此代码:

require 'haml'

puts Haml::Engine.new(%q{
%p
  %p
    %p
      = 5.times.map do |i|
      = i
}).render # => produces the output
          # you have in last example

找出关联的 Ruby 代码是什么样的。 经过一些简化,它看起来像这样:

haml_temp =  5.times.map do |i|
  _hamlout.push_text("      #{_hamlout.format_script_false_false_false_false_false_true_false(( i ));}\n", 0, false);
end

您现在可以很容易地看到,您的值已映射到表达式:

_hamlout.push_text(...)

_hamlout 这是 Haml::Buffer 的实例,这是 last line,returns 来自 push_text 方法的值:

 @real_tabs += tab_change

@real_tabs 是缩进级别。如果我们不使用缩进,那么它就是0,当涉及到一个%p时,它就变成了1等等。 tab_change 参数是 0(参见调试代码)。

因此 Haml 版本 4.0.7 的输出等于嵌套级别。这正是您的输出结果。

但在即将发布的版本 4.1.0 中,此行为可能 "broken"。比较当前 master 分支的 last line of the same method

@buffer << text

这将 return 一些文本值。