Почему URI.escape не работает при вызове ActionView:: OutputBuffer?
Я обновляю приложение от 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'
Кроме того, вызов to_s на OutputBuffer возвращает тот же класс OutputBuffer, поэтому я не могу даже преобразовать этот буфер в честную строку?
ob.to_s.class
ActionView::OutputBuffer
Конечно, вызов 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, что эффективно работает вокруг проблемы... Но мой вопрос "почему это происходит" все еще остается, например это ошибка, я должен сообщить об этом, или я делаю что-то неправильно?
Ответы
Ответ 1
Это ошибка в Rails:
При вызове gsub с блоком в ActiveSupport:: SafeBuffer глобальные переменные $1, $2 и т.д. для ссылок на подматрицы не всегда правильно установлены (больше?) при вызове блока.
Вот почему URI.escape(и любая другая функция, использующая gsub()
, не будет работать в ActiveSupprt:: Safebuffer.
Есть несколько обсуждения об этом, по-видимому, теперь самый безопасный маршрут - это позвонить в_процесс перед тем, как передать SafeBuffer во все, что может вызвать gsub, например URI.encode
, escape_javascript
и аналогичные функции.
Мой другой вопрос о to_s
возвращении того же класса - очевидно, безопасный буфер вернется сам, а не голый String, это по дизайну. Чтобы получить истинную строку, можно использовать .to_str
.
Ответ 2
Это связано с тем, что Rails 3 представила концепцию безопасных буферов
В Rails3 ваши представления защищены XSS по умолчанию, делая все рендеринг безопасным с экранированием, если вы явно не используете помощника raw()
или html_safe