Mettre à jour:
Ce problème n'a pas été correctement exploré. Le vrai problème réside à l'intérieur render :json
.
Le premier collage de code dans la question d'origine donnera le résultat attendu. Cependant, il y a toujours une mise en garde. Voir cet exemple:
render :json => current_user
n'est PAS la même chose que
render :json => current_user.to_json
Autrement dit, render :json
n'appellera pas automatiquement la to_json
méthode associée à l'objet User. En fait , si to_json
est remplacé sur le User
modèle, render :json => @user
générera le ArgumentError
décrit ci-dessous.
résumé
# works if User#to_json is not overridden
render :json => current_user
# If User#to_json is overridden, User requires explicit call
render :json => current_user.to_json
Tout cela me semble idiot. Cela semble me dire que ce render
n'est pas réellement un appel Model#to_json
lorsque le type :json
est spécifié. Quelqu'un peut-il expliquer ce qui se passe vraiment ici?
Tous les génies qui peuvent m'aider dans ce domaine peuvent probablement répondre à mon autre question: Comment créer une réponse JSON en combinant @ foo.to_json (options) et @ bars.to_json (options) dans Rails
Question originale:
J'ai vu d'autres exemples sur SO, mais je ne fais pas ce que je recherche.
J'essaie:
class User < ActiveRecord::Base
# this actually works! (see update summary above)
def to_json
super(:only => :username, :methods => [:foo, :bar])
end
end
Je reçois ArgumentError: wrong number of arguments (1 for 0)
dans
/usr/lib/ruby/gems/1.9.1/gems/activesupport-2.3.5/lib/active_support/json/encoders/object.rb:4:in `to_json
Des idées?
username
,foo
oubar
attend-elle des arguments?username
n'est pas une méthode etfoo
etbar
ne nécessitent pas de méthodes. J'ai mis à jour ma question pour montrer où se produit l'erreur.Réponses:
Vous obtenez
ArgumentError: wrong number of arguments (1 for 0)
parce qu'ilto_json
doit être remplacé par un paramètre, leoptions
hachage.Explication plus longue
to_json
,as_json
et le rendu:Dans ActiveSupport 2.3.3, a
as_json
été ajouté pour résoudre des problèmes tels que celui que vous avez rencontré. La création du json doit être distincte du rendu du json.Désormais, à tout moment
to_json
est appelé sur un objet, est appeléas_json
pour créer la structure de données, puis ce hachage est encodé en tant que chaîne JSON à l'aide deActiveSupport::json.encode
. Cela se produit pour tous les types: objet, numérique, date, chaîne, etc. (voir le code ActiveSupport).Les objets ActiveRecord se comportent de la même manière. Il existe une
as_json
implémentation par défaut qui crée un hachage qui inclut tous les attributs du modèle. Vous devez remplaceras_json
dans votre modèle pour créer la structure JSON souhaitée .as_json
, tout comme l'anciento_json
, prend un hachage d'option où vous pouvez spécifier des attributs et des méthodes à inclure de manière déclarative.Dans votre contrôleur,
render :json => o
peut accepter une chaîne ou un objet. S'il s'agit d'une chaîne, elle est transmise en tant que corps de la réponse, si c'est un objet,to_json
est appelée, ce qui se déclencheas_json
comme expliqué ci-dessus.Ainsi, tant que vos modèles sont correctement représentés avec des
as_json
remplacements (ou non), le code de votre contrôleur pour afficher un modèle devrait ressembler à ceci:La morale de l'histoire est la suivante: évitez d'appeler
to_json
directement, laissezrender
faire cela pour vous. Si vous avez besoin de modifier la sortie JSON, appelezas_json
.la source
as_json
. Comme vous pouvez le voir dans la documentation ActiveRecord :: Serialization ( api.rubyonrails.org/classes/ActiveRecord/… ), il y a très peu (pas) de documentation pour cela. Je vais essayer :)as_json
docs! Merci encore :)Si vous rencontrez des problèmes avec cela dans Rails 3, passer outre au
serializable_hash
lieu deas_json
. Cela obtiendra également votre formatage XML gratuitement :)Cela m'a pris une éternité à comprendre. J'espère que cela aide quelqu'un.
la source
serializable_hash
? Quand je l'utilise, cela change ma sortie XML suivante en enveloppant l'objet avec son nom (par exemple "quote" pour un objet de citation ") pour à la place toujours l'envelopper avec" <hash> ".to_xml
Pour les personnes qui ne veulent pas ignorer les options des utilisateurs mais qui ajoutent également les leurs:
J'espère que cela aide n'importe qui :)
la source
options
hachage avec= {}
donc ce n'est pas nécessaire lors de l'appelRemplacez non pas to_json, mais as_json. Et depuis as_json, appelez ce que vous voulez:
Essaye ça:
la source
as_json
seulement pour ActiveResource?render :json => current_user
j'obtiens le résultat par défaut attendu (tous les attributs duUser
modèle au format JSON). Quand j'ajoute laas_json
méthode à monUser
modèle et que j'essaye la même chose, j'obtiens l'erreur :(