2009-03-03 16 views
18

Sto cercando di rendere un indice di tutti gli articoli insieme a un articolo completo tramite JSON nella mia app per rotaie, ma ho qualche problema a capire come farlo.Ruby on Rails Serializzazione JSON avanzata

Ecco il mio controller ora:

if params[:id] 
    @article = Article.find(params[:id]) 
else 
    @article = Article.published.not_draft.by_recent.first 
end 

respond_to do |format| 

format.js { render :json => @article.to_json(
:except => [ :created_at, :updated_at, :draft, :id, :publish ], 
:include => { 
    :comments => { 
     :only => [:body] 
    } 
}), 
:callback => params[:callback]} 
end 

Quello che mi piacerebbe fare nella risposta è aggiungere un indice di tutti gli articoli, in questo modo:

@index = Article.find(:all, :select => 'id, title') 

L'unico modo che ho' è stato in grado di farlo, è mettere sia l'indice che l'articolo in un hash o array e poi metterlo in JSON.

@response = { :item => @article, :index => @index } 

codice completo con entrambi:

@index = Article.find(:all, :select => 'id, title') 

if params[:id] 
    @article = Article.find(params[:id]) 
else 
    @article = Article.published.not_draft.by_recent.first 
end 

@response = { :item => @article, :index => @index } 

respond_to do |format| 

format.js { render :json => @response.to_json(), :callback => params[:callback]} 

end 

Questo andrebbe bene, solo che adesso non posso specificare :include o :except e farlo rendere correttamente.

risposta

1

si dovrebbe essere in grado di nido :include, :except, ecc in questo modo:

:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}... 

Se questo non funziona, ne fanno un oggetto (ad esempio un OpenStruct) al posto di un hash.

- Markus

2

tanto per essere chiari il codice precedente funziona con il: include e: salvo. E per lavori intendo che non genera un errore. Il problema è che include commenti per ogni articolo nell'indice. Sto solo cercando di includere commenti per: item e non uno qualsiasi degli articoli elencati nell'indice.

Non ho potuto ottenere il nesting per funzionare come un hash o un oggetto OpenStruct.

Nesting on: include genera un errore, annidato su: tranne che non genera un errore, ma non viene filtrato nulla,: created_at, ecc. Ancora visualizzato.

... 

@response = { :item => @article, :index => @index } 

format.js { render :json => @response.to_json(
:except => {:item => [ :created_at, :updated_at, :draft, :id, :publish ]}, 
:include => { :item => { 
     :comments => { 
       :only => [:body] 
     } 
}}), 
:callback => params[:callback]} 
end 
1

to_json ha un'opzione: metodo che include il risultato di qualsiasi metodo è il nome, è possibile definire un metodo su quel modello che restituisce i dati aggiuntivi che volete nella vostra JSON.

28

Indica la soluzione nella tua domanda. Molto probabilmente vuoi creare un hash da renderizzare su JSON. Il modo migliore per farlo ora è fornire un'implementazione per il metodo as_json. as_json fornisce un mezzo formale per personalizzare l'output di to_json creando un hash contenente i dati che desideri codificare.

Un trattamento più approfondito di come as_son e to_json interagiscono è disponibile su Jonathan Julian's weblog.

1

(Si prega di accettare una risposta)

Penso che il link che nirvdrum dato tiene la vostra risposta. Rispondo solo perché nessuno ha menzionato lo encode_json.

Nel tuo caso dovresti avere a che fare solo con as_json.O costruendo un hash (con varie chiamate a as_json) e inviandolo a render :json => ... (senza la chiamata a to_json) o semplicemente implementando as_json sul modello e lasciando che le rotaie facciano tutto il lavoro. (Ma ho il sospetto che tu abbia bisogno del primo.)

Se hai davvero bisogno di un po 'di fantasia nella tua risposta di rendering, puoi implementare encode_json nelle tue classi (ancora, non to_json). Per esempio:

class JsEmptyClosure 
    def encode_json(*args) 
    "jQuery[\"noop\"] || function(){}" 
    end 
    def as_json(*args) self end 
end 

Questo risponde ora al to_json con js valide (ma nota che non è in realtà JSON).

0

Grazie per la domanda, sono in grado di personalizzare il mio formato JSON per un modello con diverse associazioni.

rende JSON: @ posts.to_json (

: tranne => [: created_at,: updated_at,: user_id],

: include => {

: user => {: only => [: email,: telefono]},

: posizione => {: solo => [: titolo,: lat,: lon,: strada,: città,: stato, : codice postale] },

.210

: uploads => {: solo => [: Immagine]}

}
)

0

mi sento di raccomandare di sovraccaricare il metodo attributi per restituire un hash Alternativa che verrà utilizzato automaticamente in uscita to_json .

class Article 
    def attributes 
    { ... } # define your hash that you want to return at the '...' 
    end 
end 

A me questo sembra molto più semplice di gingillarsi con to_json direttamente.