我正在通过Pickaxe书(第281页)的Haml部分编写代码:
require 'haml'
engine = Haml::Engine.new(%{
%body
#welcome-box
%p= greeting
%p
As of
= Time.now
the reasons you gave were:
%table
%tr
%th Reason
%th Rank
- for reason in reasons
%tr
%td= reason[:reason_name]
%td= reason[:rank]
})
data = {
greeting: 'Hello, Dave Thomas',
reasons: [
{ reason_name: 'flexible', rank: '87' },
{ reason_name: 'transparent', rank: '76' },
{ reason_name: 'fun', rank: '94' },
]
}
puts engine.render(nil, data)
运行它会产生错误:
/Users/andrekibbe/.rvm/gems/ruby-2.2.1/gems/haml-4.0.7/lib/haml/engine.rb:136:in `block in render': can't modify frozen NilClass (RuntimeError)
from /Users/andrekibbe/.rvm/gems/ruby-2.2.1/gems/haml-4.0.7/lib/haml/engine.rb:135:in `instance_eval'
from /Users/andrekibbe/.rvm/gems/ruby-2.2.1/gems/haml-4.0.7/lib/haml/engine.rb:135:in `ensure in render'
from /Users/andrekibbe/.rvm/gems/ruby-2.2.1/gems/haml-4.0.7/lib/haml/engine.rb:135:in `render'
from haml_example.rb:17:in `<main>'
我对Haml :: Engine#render语法感到困惑,根据documentation,它将块作为三个参数中的最后一个 - 而在上面的代码中,块是两个参数中的第一个。为什么块应该设置为“nil”?
答案 0 :(得分:2)
您使用nil
作为范围(Engine#render
的第一个参数)
在Ruby 2.2中冻结了nil
。
p nil.frozen? # Prints false in Ruby 2.0
p nil.frozen? # Prints true in Ruby 2.2
无法修改冻结对象。因此,Ruby不允许Haml在instance_eval
范围内执行nil
。这就是我们看到错误的原因。
您的代码在Ruby 2.0中运行良好。我的猜测是书中的例子是在Ruby 2.2之前编写的。
要修复您的代码,请使用以下内容:
puts engine.render(Object.new, data)
PS:错误与render
的第三个参数无关。您可以查看code of engine.rb进行确认。