Comment construire une réponse JSON composé de plusieurs modèles dans les Rails
Tout d'abord, le résultat souhaité
J'ai User
et Item
modèles. J'aimerais construire une réponse JSON qui ressemble à ceci:
{
"user":
{"username":"Bob!","foo":"whatever","bar":"hello!"},
"items": [
{"id":1, "name":"one", "zim":"planet", "gir":"earth"},
{"id":2, "name":"two", "zim":"planet", "gir":"mars"}
]
}
Cependant, mon User
et Item
modèle ont plus d'attributs que ceux. J'ai trouvé un moyen d'obtenir que cela fonctionne, mais méfiez-vous, c'est pas joli... s'il vous Plaît aider...
Mise à jour
La section suivante contient la question d'origine. La dernière section présente la nouvelle solution.
Mon hacks
home_controller.rb
class HomeController < ApplicationController
def observe
respond_to do |format|
format.js { render :json => Observation.new(current_user, @items).to_json }
end
end
end
observation.rb
# NOTE: this is not a subclass of ActiveRecord::Base
# this class just serves as a container to aggregate all "observable" objects
class Observation
attr_accessor :user, :items
def initialize(user, items)
self.user = user
self.items = items
end
# The JSON needs to be decoded before it's sent to the `to_json` method in the home_controller otherwise the JSON will be escaped...
# What a mess!
def to_json
{
:user => ActiveSupport::JSON.decode(user.to_json(:only => :username, :methods => [:foo, :bar])),
:items => ActiveSupport::JSON.decode(auctions.to_json(:only => [:id, :name], :methods => [:zim, :gir]))
}
end
end
Regarde Ma! Pas plus de hacks!
Remplacer as_json
au lieu
La ActiveRecord::Sérialisation#as_json docs sont assez rares. Voici la bref:
as_json(options = nil)
[show source]
Pour plus d'informations sur to_json
vs as_json
, voir la accepté de répondre pour Primordial to_json dans les Rails 2.3.5
Le code sans hacks
de l'utilisateur.rb
class User < ActiveRecord::Base
def as_json(options)
options = { :only => [:username], :methods => [:foo, :bar] }.merge(options)
super(options)
end
end
élément.rb
class Item < ActiveRecord::Base
def as_json(options)
options = { :only => [:id, name], :methods => [:zim, :gir] }.merge(options)
super(options)
end
end
home_controller.rb
class HomeController < ApplicationController
def observe
@items = Items.find(...)
respond_to do |format|
format.js do
render :json => {
:user => current_user || {},
:items => @items
}
end
end
end
end
OriginalL'auteur maček | 2010-04-03
Vous devez vous connecter pour publier un commentaire.
ÉDITÉ à utiliser
as_json
au lieu deto_json
. Voir Comment remplacer to_json dans les Rails? pour une explication détaillée. Je pense que c'est la meilleure réponse.Vous pouvez rendre le JSON que vous voulez dans le contrôleur sans avoir besoin de l'aide du modèle.
Assurez-vous que
ActiveRecord::Base.include_root_in_json
est définie sur false, sinon vous allez obtenir un "utilisateur" de l'attribut à l'intérieur de "l'utilisateur". Malheureusement, on dirait des Tableaux de ne pas passeroptions
vers le bas à chaque élément, de sorte que lecollect
est nécessaire."user" => current
que nous sommes tous "savoir et de l'amour"?Julian,
ActiveRecord::Base.include_root_in_json
est fixé àfalse
et c'est exactement ce que j'ai devrait, mais pas exactement ce que je espérait. L'interneto_json
appels se sont échappés parrender :json
. Par exemple, au lieu de{"user": {"username": "Bob!"}}
je suis{"user": "{\"username\": \"Bob!\"}"}
🙁fixe de hachage syntaxe ruby 1.8 style
Bigg, c'est en fait une faute de frappe. (Et une erreur de syntaxe, jamais pour Ruby 1.9). Il signifie
{:user => current_user...}
Vous pouvez toujours
render :json => {}
et simplement l'accumulation de hachage à la main sans appeler to_json sur les modèles. Ou utiliserdecode
comme vous l'avez déjà trouvé. De toute façon, il n'y a pas besoin d'un modèle distinct.OriginalL'auteur Jonathan Julian
Au cas où quelqu'un est à la recherche d'une solution de rechange pour cela, voici comment j'ai résolu ce problème dans les Rails 4.2:
Ceci renvoie à la version sérialisée de deux objets JSON, accessible via
response.user
etresponse.item
.OriginalL'auteur Justin Manche
Il y a beaucoup de nouvelles Gemmes pour la construction de JSON maintenant, pour ce cas, le plus approprié que j'ai trouvé est Jsonify:
https://github.com/bsiggelkow/jsonify
https://github.com/bsiggelkow/jsonify-rails
Cela vous permet de construire l'ensemble des attributs et des tableaux à partir de vos modèles.
OriginalL'auteur mtkd
De travail réponse #2 Pour éviter le problème de votre json être "échappé", construire la structure de données à la main, puis d'appeler to_json sur elle une fois. Il peut être un peu verbeux, mais vous pouvez le faire dans le contrôleur, ou abstrait à l'individu des modèles comme
to_hash
ou quelque chose.to_json
dans les Rails 2.3.5" (stackoverflow.com/questions/2572284/...) la question avant? 😉Afin de résoudre vos problèmes, créer un
to_hash
dans chacun de vos modèles et de construire vous-même. Un peu de code pour un couple de des maux de tête.Je vais donner un coup de cette.
veuillez mettre à jour
@items.each
à lire@items.collect
.Array#each
renvoie l'original@items
tableau. Ce n'est que légèrement plus propre que ce que j'avais avant, mais il me semble que je devrais être en mesure de puiser dans laas_json
outo_json
méthodes en quelque sorte; je veux dire, c'est qu'elles sont faites. Il est très possible que de nombreux autres objets apparaissent dans la partie "Observation" de hachage, donc faire tout ce travail supplémentaire pour chacun semble comme il pourrait être un casse-tête de sa propre. Si une réponse n'apparaît pas dans quelques jours, je vais marquer cette acceptée. Merci encore 🙂OriginalL'auteur Jonathan Julian