2010-09-15 17 views
16

Sto usando respond_with e tutto è collegato correttamente per ottenere dati correttamente. Voglio personalizzare i formati restituiti json, xml e foobar in modo DRY, ma non riesco a capire come farlo utilizzando il numero limitato :only e :include. Questi sono grandi quando i dati sono semplici, ma con reperti complessi, non sono all'altezza di ciò che voglio.Come personalizzare la risposta to_son in Rails 3

Diciamo che ho un post che has_many immagini

def show 
    @post = Post.find params[:id] 
    respond_with(@post) 
end 

voglio includere le immagini con la risposta così ho potuto fare questo:

def show 
    @post = Post.find params[:id] 
    respond_with(@post, :include => :images) 
end 

ma io davvero non desidera inviare il tutto l'oggetto dell'immagine, solo l'url. In aggiunta a questo, voglio davvero essere in grado di fare qualcosa di simile anche questo (pseudocodice):

def show 
    @post = Post.find params[:id] 
    respond_with(@post, :include => { :foo => @posts.each.really_cool_method }) 
end 

def index 
    @post = Post.find params[:id] 
    respond_with(@post, :include => { :foo => @post.really_cool_method }) 
end 

... ma tutto in modo SECCO. Nei vecchi progetti di rotaie, ho utilizzato costruttori XML per personalizzare l'output, ma replicandolo su json, xml, html, qualunque cosa non sembri giusta. Devo immaginare che i guru delle rotaie abbiano messo qualcosa in Rails 3 che non sto realizzando per questo tipo di comportamento. Idee?

risposta

7

Non sono le rotaie 3 built-in modo, ma ho trovato una grande gemma che è mantenuto attivamente on Rails 3: acts_as_api

+1

Questo link è un 404. – lashleigh

+2

https://github.com/fabrik42/acts_as_api – coneybeare

21

È possibile ignorare as_json nel modello. Qualcosa di simile:

class Post < ActiveRecord::Base 
    def as_json(options = {}) 
    { 
     attribute: self.attribute, # and so on for all you want to include 
     images: self.images, # then do the same `as_json` method for Image 
     foo:  self.really_cool_method 
    } 
    end 
end 

e rotaie si prende cura di tutto il resto quando si utilizza respond_with. non del tutto sicuro di quello che options viene impostata a, ma probabilmente le opzioni che si danno a respond_with (:include, :only e così via)

+2

Vuole cambiare as_json, as_xml, as_foobar tutto in un posto. – scragz

+0

Sì, questo non è proprio DRY – coneybeare

+0

'include' non usa' as_json', questo non aiuta. – Meekohi

8

probabilmente è troppo tardi, ma ho trovato una soluzione più DRY scavare attraverso le rotaie docs. Questo funziona in mio breve test, ma potrebbe essere necessario qualche ritocco:

# This method overrides the default by forcing an :only option to be limited to entries in our 
# PUBLIC_FIELDS list 
def serializable_hash(options = nil) 
    options ||= {} 
    options[:only] ||= [] 
    options[:only] += PUBLIC_FIELDS 
    options[:only].uniq! 
    super(options) 
end 

Questo permette in sostanza di avere un elenco di campi che sono ammessi per la vostra API pubblica, e non è possibile esporre accidentalmente l'intero oggetto. Puoi ancora esporre manualmente campi specifici, ma per impostazione predefinita il tuo oggetto è sicuro per .to_json, .to_xml, ecc.

+0

In realtà, questo dovrebbe probabilmente solo predefinito quando: solo non è specificato, altrimenti cambia l'intenzione di usare: only. Oh, bene, il mio punto è lo stesso. – Nerdmaster

+0

Sostituire serializable_hash ha funzionato meglio per me aggiungere alcuni metodi come attributi in Rails 3.2.8, grazie! – Docunext

+0

Questa è la risposta corretta. Funziona anche su Rails 4. – Meekohi