I’m upgrading an application from Rails 2 to Rails 3. Apparently, calling render() now returns ActionView::OutputBuffer and not String. I need to pass the results of render() to URI.escape(), and this fails with exception…
Here is my brief testing in the console
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'
Moreover, calling to_s on OutputBuffer returns same OutputBuffer class, so I cannot even convert this buffer into a honest string?
ob.to_s.class
ActionView::OutputBuffer
Of course, calling URI.escape(“test test”) returns “test%20test” as expected, so this is not URI problem.
Environment:
- ruby 1.9.3p125 (2012-02-16 revision 34643) [i686-linux]
- Rails 3.2.1
My question is: Why does this happen and how can I work around this issue?
Update: Apparently, using '' + ob as a form of ob.to_s converts OutputBuffer to String, which effectively works around the problem… But my question ‘why does this happen‘ still remains, e.g. is this a bug, should I report it, or I’m doing something wrong?
This is a bug in Rails:
This is why URI.escape (and any other function that uses
gsub()will fail on ActiveSupprt::Safebuffer.There are several discussions about this, apparently the safest route right now is to call to_str before passing SafeBuffer to anything that can call gsub, e.g.
URI.encode,escape_javascriptand similar functions.My other quesion about
to_sreturning the same class – obviously safe buffer will return itself and not a bare String, this is by design. In order to get a true String,.to_strcan be used.