web-dev-qa-db-fra.com

Gestion des modèles JSON dans JS/ERB dans Rails 3

Je n'ai aucune difficulté à passer des appels AJAX typiques vers et depuis Rails (3) avec des objets JSON et jQuery-Rails (bibliothèque jQuery plus un fichier spécial Rails.js).

Toutefois, dans un contrôleur, je souhaite retourner du code JSON dans un modèle erb (create.js.erb) après un appel AJAX.

J'ai essayé toutes les combinaisons de choses dans le contrôleur (@ object.to_json, '[{"content": "hello world"} ", etc.) et dans le modèle lui-même (JSON.parse (), guillemets simples, guillemets, etc.), mais l’objet continue à être rendu comme ceci:

'[{"groups":{},"created_at":"2010-09-21T03:49:34Z" ...

et par conséquent, mon code jQuery ne peut pas l’analyser et j’obtiens des erreurs. 

Comment dois-je préparer mon objet dans le contrôleur et de quelle syntaxe erb ai-je besoin dans la vue pour qu'il soit rendu en tant qu'objet JSON valide?

Merci beaucoup!

32
Michael Waxman

Je ne suis pas sûr que ce soit la cause, mais vous pouvez aussi essayer de jouer avec la méthode html_safe. ERB échappe peut-être à votre code JSON car il pense que le langage HTML n'est pas sûr. Essayez d'appeler cette méthode en utilisant la chaîne:

@object.to_json.html_safe
54
alex.zherdev

Utiliser html_escape ou raw seul vous laissera vulnérable à XSS .

Au lieu de cela, définissez une version appropriée de l’assistant 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

Utilisez-le comme ceci:

<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>

Voir this post pour plus de détails.

Sachez qu'il existe un conflit de noms entre j, alias json_escape dans ERB :: Util et j, alias à escape_javascript dans ActionView :: Helpers :: JavaScriptHelper. J'espère que l'alias JavaScriptHelper sera renommé js.

32
John

Pour renvoyer json, vous devez écrire votre rendu dans le contrôleur comme suit:

render :json => @object

et le .to_json sera automatiquement appelé.

Si vous souhaitez inclure des relations, vous pouvez procéder comme suit:

render :json => @post.to_json(:include => [:comments, :authors])

Je ne suis pas sûr si cela fonctionnerait d'utiliser un erb pour rendre votre JSON.

1
nathanvda

Seul to_json.html_safe est nécessaire: 

> `'<script>'.to_json`
=> "\"\\u003cscript\\u003e\""

Patch permettant à to_json de répondre à html_safe? et de renvoyer true automatiquement:

# 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
0
brauliobo

Vous pouvez appeler render dans votre contrôleur, mais ce sera un problème si vous devez éventuellement rendre plus de quelques partiels pour une insertion ultérieure de dom par le gestionnaire. J'avais besoin de définir plusieurs fragments html dans un hachage, et j'ai pu renvoyer erb qui utilise fondamentalement hash.to_json.html_safe comme neutrino l'indique ci-dessus et me permet d'afficher plusieurs partiels dans le processus. 

0
wkhatch