Haml::Engine#渲染:"can't modify frozen NilClass (RuntimeError)"
Haml::Engine#render: "can't modify frozen NilClass (RuntimeError)"
我正在研究 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"?
您正在使用 nil
作为 scope(Engine#render
的第一个参数)
nil
冻结在 Ruby 2.2.
p nil.frozen? # Prints false in Ruby 2.0
p nil.frozen? # Prints true in Ruby 2.2
无法修改冻结的对象。因此,Ruby 不允许 Haml 在 nil
作用域上执行 instance_eval
。这就是我们看到错误的原因。
您的代码在 Ruby 2.0 中运行良好。我的猜测是书上的例子写在Ruby 2.2.
之前
要修复您的代码,请使用以下内容:
puts engine.render(Object.new, data)
PS:错误与render
的第三个参数无关。你可以看看code of engine.rb来确认。
我正在研究 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"?
您正在使用 nil
作为 scope(Engine#render
的第一个参数)
nil
冻结在 Ruby 2.2.
p nil.frozen? # Prints false in Ruby 2.0
p nil.frozen? # Prints true in Ruby 2.2
无法修改冻结的对象。因此,Ruby 不允许 Haml 在 nil
作用域上执行 instance_eval
。这就是我们看到错误的原因。
您的代码在 Ruby 2.0 中运行良好。我的猜测是书上的例子写在Ruby 2.2.
之前要修复您的代码,请使用以下内容:
puts engine.render(Object.new, data)
PS:错误与render
的第三个参数无关。你可以看看code of engine.rb来确认。