在ActionView :: OutputBuffer上调用时为什么URI.escape失败?

hai*_*img 14 ruby-on-rails ruby-on-rails-3

我正在将应用程序从Rails 2升级到Rails 3.显然,render()现在调用返回ActionView::OutputBuffer而不是String.我需要将结果传递render()URI.escape(),这会失败,但异常......

这是我在控制台中的简短测试

ob = ActionView::OutputBuffer.new("test test")
URI.escape(ob)
    `NoMethodError: undefined method 'each_byte' for nil:NilClass`. 
        from /opt/ruby19/lib/ruby/1.9.1/uri/common.rb:307:in `block in escape'
        from ..../ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/core_ext/string/output_safety.rb:160:in `gsub'
        from ..../ruby/1.9.1/gems/activesupport-3.2.1/lib/active_support/core_ext/string/output_safety.rb:160:in `gsub'
        from /opt/ruby19/lib/ruby/1.9.1/uri/common.rb:304:in `escape'
        from /opt/ruby19/lib/ruby/1.9.1/uri/common.rb:623:in `escape'
Run Code Online (Sandbox Code Playgroud)

而且,在OutputBuffer上调用to_s会返回相同的OutputBuffer类,所以我甚至无法将此缓冲区转换为诚实的字符串?

ob.to_s.class 
    ActionView::OutputBuffer
Run Code Online (Sandbox Code Playgroud)

当然,调用URI.escape("test test")会按预期返回"test%20test",因此这不是URI问题.

环境:

  • ruby 1.9.3p125(2012-02-16修订版34643)[i686-linux]
  • Rails 3.2.1

我的问题是:为什么会发生这种情况,我该如何解决这个问题呢?

更新:显然,使用'' + ob作为一种ob.to_s将OutputBuffer转换为String 的形式,它可以有效地解决问题...但我的问题' 为什么会发生这种情况 '仍然存在,例如这是一个错误,我应该报告,还是我做错了什么?

hai*_*img 19

这是Rails中的一个错误:

当使用ActiveSupport :: SafeBuffer上的块调用gsub时,在调用块时,用于引用子匹配的全局变量$ 1,$ 2等并不总是正确设置(不再是?).

这就是URI.escape(以及任何其他使用的函数gsub()在ActiveSupprt :: Safebuffer上失败的原因.

几个 讨论此事,显然是现在最安全的途径是通过SafeBuffer到任何可以称之为GSUB,如之前调用to_str URI.encode,escape_javascript以及类似功能.

关于to_s返回同一个类的另一个问题- 显然安全的缓冲区将返回自身,而不是一个裸字符串,这是设计的.为了获得真正的String,.to_str可以使用.