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...
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:
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:
When calling gsub with a block on an ActiveSupport::SafeBuffer the global variables $1, $2, etc. for referencing submatches are not always properly set (anymore?) when the block is called.
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_javascript
and similar functions.
My other quesion about to_s
returning 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_str
can be used.
This is due to the fact that Rails 3 introduced the concept of safe buffers
In Rails3 your Views are protected by XSS by default by making all rendering be safely escaped unless you explicitly use the raw()
helper or html_safe
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With