Haml :: Engine#render:“无法修改冻结的NilClass(RuntimeError)”

时间:2015-08-29 16:51:08

标签: ruby haml

我正在通过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”?

1 个答案:

答案 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进行确认。