Обработка JSON в шаблоне JS/ERB в Rails 3
У меня нет проблем с типичными вызовами AJAX и из Rails (3) с объектами JSON и jQuery-rails (библиотека jQuery плюс специальный файл rails.js).
Однако в одном контроллере я хочу ВОЗВРАТАТЬ некоторый JSON в шаблон erb (create.js.erb) после вызова AJAX.
Я пробовал каждую комбинацию вещей в контроллере (@object.to_json, '[{ "content": "hello world" }] и т.д.) и в самом шаблоне (JSON.parse(), одинарные кавычки, двойные кавычки и т.д.), но объект продолжает делать так:
'[{"groups":{},"created_at":"2010-09-21T03:49:34Z" ...
и, как результат, мой код jQuery не может разобрать его, и я получаю ошибки.
Как мне нужно подготовить мой объект в контроллере и какой синтаксис erb мне нужен в представлении, чтобы он отображался как действительный объект JSON?
Большое спасибо!
Ответы
Ответ 1
Я не уверен, что это причина, но вы также можете попробовать играть с помощью метода html_safe
. ERB может ускользнуть от вашего JSON, потому что он считает его безопасным без html. Попробуйте вызвать этот метод при использовании строки:
@object.to_json.html_safe
Ответ 2
Только с помощью html_escape
или raw
вы оставите уязвимым для XSS.
Вместо этого определите разумную версию помощника json_escape
(a.k.a. j
):
module ActionView::Base
def json_escape(s)
result = s.to_s.gsub('/', '\/')
s.html_safe? ? result.html_safe : result
end
alias j json_escape
end
Используйте его следующим образом:
<script>
var Accounts = new Backbone.Collection;
Accounts.reset(<%=j @accounts.to_json.html_safe %>);
var Projects = new Backbone.Collection;
Projects.reset(<%=j @projects.to_json(:collaborators => true).html_safe %>);
</script>
Подробнее см. этот пост.
Помните, что существует конфликт имен между j
aliased до json_escape
в ERB:: Util и j
с псевдонимом escape_javascript
в ActionView:: Helpers:: JavaScriptHelper. Я надеюсь, что псевдоним JavaScriptHelper будет переименован в js
.
Ответ 3
Чтобы вернуть json
, вы должны записать рендер в контроллер следующим образом:
render :json => @object
и автоматически будет вызываться .to_json
.
Если вы хотите включить некоторые отношения, вы можете сделать следующее:
render :json => @post.to_json(:include => [:comments, :authors])
Я не уверен, что это будет работать, чтобы использовать erb для рендеринга вашего json.
Ответ 4
Вы можете вызывать рендер в своем контроллере, но это будет проблемой, если вам нужно будет отобразить больше, чем несколько частичных для последующего ввода содержимого обработчиком. Мне нужно было установить несколько html-фрагментов в хэш, и мне удалось вернуть erb, который в основном использует hash.to_json.html_safe, как предлагает нейтрино, и позволяет мне отображать несколько партикулов в процессе.
Ответ 5
Требуется только to_json.html_safe
:
> `'<script>'.to_json`
=> "\"\\u003cscript\\u003e\""
Patch, чтобы to_json
ответил на html_safe?
и автоматически возвратил true
:
# just use .to_json instead of .to_json.html_safe
ActiveSupport::JSON.class_eval do
class << self
def encode_with_html_safe *args
self.encode_without_html_safe(*args).html_safe
end
alias_method_chain :encode, :html_safe
end
end