在 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 一些文本值。
我正在使用 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 一些文本值。