Подтвердить что ты не робот

Обработка 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?

Большое спасибо!

4b9b3361

Ответ 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