Builder的XmlMarkup对象会丢失常量吗?

时间:2016-07-28 06:54:07

标签: ruby namespaces constants metaprogramming eigenclass

我尝试将遗留应用程序从Ruby 1.8.7升级到2.2.3。之后,builder模板的呈现会引发有关未知类的错误。

  

未初始化的常量Builder :: XmlMarkup :: BigDecimal(NameError)

似乎在Builder :: XmlMarkup中,类之类的常量消失了。

### example.xml.builder (template) ###
BigDecimal.new('23') # no error

class << xml
  def some
    data(BigDecimal.new('23')) # raises an error in 2.2.3
  end
end

xml.test { xml.some }

### main script ###
require 'rubygems'
require 'builder'
require 'bigdecimal'

def eval_script(file)
  xml = Builder::XmlMarkup.new
  binding.eval(File.read(file), file)
  xml.target!
end

template = File.join(File.dirname(__FILE__), 'example.xml.builder')
puts eval_script(template)
# Ruby 1.8.7 / builder 3.2.0 => <test><data>0.23E2</data></test>
# Ruby 2.2.3 / builder 3.2.2 => ./eval_script.rb:5:in `some': uninitialized constant Builder::XmlMarkup::BigDecimal (NameError)

我没有找到这种行为的理由。我该如何解决这个问题?

BTW:方法查找遇到了同样的问题,例如format('%d', 42)返回完整的XML文档但没有在Ruby 2.2.3中调用Kernel.format

1 个答案:

答案 0 :(得分:0)

我找到了一个覆盖const_missing的解决方法,该方法必须应用于每个模板文件。到目前为止,它对遗留应用程序起作用。

### example.xml.builder (template) ###
class << xml
  def self.const_missing(name)
    super rescue ::Object.const_get(name)
  end

  def some
    data(BigDecimal.new('23'))
  end
end

xml.test { xml.some }

但每次使用常量BigDecimal时,它都会触发const_missing,然后引发NameError并调用Object方法。