Rendu JSON dans le contrôleur


103

Je lisais un livre et dans un chapitre sur les contrôleurs quand il parle de rendu, pour JSON, il a un exemple comme celui-ci mais ne rentre pas dans les détails, donc je ne pouvais pas comprendre la situation dans laquelle cet exemple s'inscrit:

render :json => @projects, :include => tasks

Et aussi un exemple avec JSONP en l'utilisant avec des fonctions de rappel:

render :json => @record, :callback => 'updateRecordDisplay'

Quelqu'un peut-il expliquer cela?

Réponses:


127

Vous retournerez normalement JSON soit parce que:

A) Vous construisez une partie / l'ensemble de votre application en tant qu'application à page unique (SPA) et vous avez besoin de votre JavaScript côté client pour pouvoir extraire des données supplémentaires sans recharger complètement la page.

ou

B) Vous créez une API que des tiers consommeront et vous avez décidé d'utiliser JSON pour sérialiser vos données.

Ou, peut-être, vous mangez votre propre dogfood et faites les deux

Dans les deux cas render :json => some_data, les données fournies seront JSON-ify. La :callbackclé du deuxième exemple nécessite un peu plus d'explications (voir ci-dessous), mais c'est une autre variante de la même idée (renvoyer des données d'une manière que JavaScript peut facilement gérer.)

Pourquoi :callback?

JSONP (le deuxième exemple) est un moyen de contourner la politique de même origine qui fait partie de la sécurité intégrée de chaque navigateur. Si vous avez votre API à api.yoursite.comet que vous allez servir votre application hors de services.yoursite.comvotre JavaScript, vous ne pourrez pas (par défaut) faire des XMLHttpRequestrequêtes (XHR - aka ajax) de servicesà api. La façon dont les gens ont contourné cette limitation (avant la finalisation de la spécification de partage de ressources inter-origines ) consiste à envoyer les données JSON depuis le serveur comme s'il s'agissait de JavaScript au lieu de JSON ). Ainsi, plutôt que de renvoyer:

{"name": "John", "age": 45}

le serveur renverrait à la place:

valueOfCallbackHere({"name": "John", "age": 45})

Ainsi, une application JS côté client pourrait créer une scriptbalise pointant sur api.yoursite.com/your/endpoint?name=Johnet faire valueOfCallbackHereappeler la fonction (qui devrait être définie dans le JS côté client) avec les données de cette autre origine .)


et vaut-il mieux ne pas utiliser ces techniques du tout et utiliser à la place JSON-JBuilder et Eager Loading? Ou je suis confus et ce sont deux choses différentes.?

1
@ user1899082 - ces techniques sont en fait des concepts de niveau inférieur à ce qui vous préoccupera lorsque vous utiliserez JBuilder, par exemple - il n'y a aucune raison pour que vous ne puissiez pas utiliser JBuilder pour rendre la sérialisation de vos objets plus facile à l'intérieur de vos to_jsonméthodes - mélange et faire correspondre les deux render :json => some_object_that_uses_JBuilder_to_render_its_jsonest (pour autant que je sache) licite.
Sean Vieira

Merci Sean, votre explication m'a aidé à savoir sur le rendu de json avec rappel, cela a résolu l'un de mes problèmes.
Abhi

67

Qu'est ce que tu veux savoir exactement? ActiveRecord a des méthodes qui sérialisent les enregistrements dans JSON. Par exemple, ouvrez votre console de rails et entrez ModelName.all.to_jsonet vous verrez la sortie JSON. render :jsonappelle to_jsonet renvoie essentiellement le résultat au navigateur avec les en-têtes corrects. Ceci est utile pour les appels AJAX en JavaScript où vous souhaitez renvoyer des objets JavaScript à utiliser. De plus, vous pouvez utiliser lecallback option pour spécifier le nom du rappel que vous souhaitez appeler via JSONP.

Par exemple, disons que nous avons un User modèle qui ressemble à ceci:{name: 'Max', email:' m@m.com'}

Nous avons également un contrôleur qui ressemble à ceci:

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        render json: @user
    end
end

Maintenant, si nous faisons un appel AJAX en utilisant jQuery comme ceci:

$.ajax({
    type: "GET",
    url: "/users/5",
    dataType: "json",
    success: function(data){
        alert(data.name) // Will alert Max
    }        
});

Comme vous pouvez le voir, nous avons réussi à obtenir l'utilisateur avec l'ID 5 de notre application rails et à l'utiliser dans notre code JavaScript car il a été renvoyé en tant qu'objet JSON. L'option de rappel appelle simplement une fonction JavaScript du named passé avec l'objet JSON comme premier et unique argument.

Pour donner un exemple de l' callbackoption, jetez un œil à ce qui suit:

class UsersController < ApplicationController
    def show
        @user = User.find(params[:id])
        render json: @user, callback: "testFunction"
    end
end

Nous pouvons maintenant créer une requête JSONP comme suit:

function testFunction(data) {
    alert(data.name); // Will alert Max
};

var script = document.createElement("script");
script.src = "/users/5";

document.getElementsByTagName("head")[0].appendChild(script);

La motivation pour utiliser un tel rappel est généralement de contourner les protections du navigateur qui limitent le partage de ressources entre origines (CORS). Cependant, JSONP n'est plus beaucoup utilisé, car il existe d'autres techniques pour contourner CORS qui sont plus sûres et plus faciles.


Pouvez-vous étendre un peu votre exemple? Ajouter une callback:option dans la renderméthode, puis l'afficher dans l' Ajaxappel.
Arup Rakshit

15

Pour l'instance de

render :json => @projects, :include => :tasks

Vous indiquez que vous souhaitez effectuer @projectsle rendu au format JSON et inclure l'association taskssur le modèle de projet dans les données exportées.

Pour l'instance de

render :json => @projects, :callback => 'updateRecordDisplay'

Vous indiquez que vous souhaitez effectuer @projectsle rendu au format JSON et envelopper ces données dans un appel javascript qui affichera un peu comme:

updateRecordDisplay({'projects' => []})

Cela permet aux données d'être envoyées à la fenêtre parente et de contourner les problèmes de falsification intersites.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.