2012-03-31 16 views
48

Voglio dire PUT su rotaie ed evitare di ottenere 204. Sto usando questo schema:Risposta semplice con binari che evitano 204 da PUT

class SomeController < ApplicationController 
    respond_to :json 

    def update 
    # ... 
    respond_with(some_object) 
    end 
end 

Tuttavia, quando faccio una put per aggiornare, ottengo un back 204. Mi rendo conto che questo è completamente valido ecc., Ma desidero esplicitamente il ritorno del contenuto. Posso sovrascriverlo in una certa misura:

def update 
    respond_with(some_object) do |format| 
    format.json{render json: some_object} 
    end 
end 

ma questo sembra un po 'troppo pratico per le guide. C'è un modo più idiomatico di evitare uno 204 e richiedere l'invio dell'intero contenuto? Questo è Rails 3.2.

In sintesi: desidero i binari massimamente idiomatici che evitino uno 204.

risposta

29

Ho creato un risponditore personalizzato che restituisce sempre la mia risorsa codificata JSON anche su PUT/POST.

Ho messo questo file in lib/responders/json_responder.rb. La tua directory /lib dovrebbe essere caricata automaticamente.

module Responders::JsonResponder 
    protected 

    # simply render the resource even on POST instead of redirecting for ajax 
    def api_behavior(error) 
    if post? 
     display resource, :status => :created 
    # render resource instead of 204 no content 
    elsif put? 
     display resource, :status => :ok 
    else 
     super 
    end 
    end 
end 

Ora, modificare esplicitamente il controller che richiede questo comportamento o posizionarlo nel controller dell'applicazione.

class ApplicationController < ActionController::Base 

    protect_from_forgery 

    responders :json 

end 

Si dovrebbe ora ottenere JSON codificato risorse indietro sul PUT.

+8

Vorrei aggiungere che è necessario gemma il 'responder' essere in grado di utilizzare il metodo responder nel controller. – iterion

3

Cosa c'è di sbagliato con semplicemente facendo:

def update 
    some_object = SomeObject.update() 
    render json: some_object 
end 
+2

Non si otterranno codici di risposta http o errori corretti –

+0

Come il commento sopra detto, non si ottiene alcun feedback sul fatto che "aggiornamento" sia riuscito o meno. – Leito

11

Questo comportamento sembra intenzionale a cadere in linea con le specifiche HTTP, e "ideale" si dovrebbe essere sparando una richiesta aggiuntiva GET per vedere i risultati. Tuttavia, sono d'accordo nel mondo reale preferirei che restituisse il JSON.

@ soluzione jpfuentes2 sopra dovrebbe fare il trucco (è molto simile alla richiesta di pull qui di seguito), ma sono riluttanti ad applicare tutto ciò che è l'applicazione di patch rotaie interni, come potrebbe essere un vero e proprio dolore per l'aggiornamento tra le versioni principali, in particolare se non si hanno test per questo (e diciamocelo, gli sviluppatori spesso risparmiano sui test del controller).

Riferimenti

+0

Grazie per la risposta. Hai ragione, preferirei fare un altro '$ .get' da' JS' piuttosto che iniziare a combattere un framework. – jibiel

6

Giusto per chiarire, non è necessario la gemma responder per fare questo ... si può solo fare:

config/inizializzatori/responder_with_put_content.rb

class ResponderWithPutContent < ActionController::Responder 
    def api_behavior(*args, &block) 
    if put? 
     display resource, :status => :ok 
    else 
     super 
    end 
    end 
end 

e poi o (per tutte le azioni aggiornamenti di essere colpiti):

class ApplicationController < ActionController::Base 
    def self.responder 
    ResponderWithPutContent 
    end 
end 

o nella vostra azione:

def update 
    foo = Foo.find(params[:id]) 
    foo.update_attributes(params[:foo]) 
    respond_with foo, responder: ResponderWithPutContent 
end 
+0

Hai salvato la mia giornata. (Y) –

9

Come alternativa meno invasiva, è possibile passare un Opzione json: per il richiamo del metodo respond_with all'interno del controller update azione, come questa:

Concesso sembra un po 'disordinato dover ripetere l'oggetto due volte negli argomenti, ma ti darà quello che vuoi, la rappresentazione json dell'oggetto nella risposta di una richiesta PUT, e tu non è necessario utilizzare il modo render json:, che non offre i vantaggi dei soccorritori.

Tuttavia, se si dispone di molti controller con questa situazione, la personalizzazione dei responder, come mostrato da jpfuentes2 nell'animatore accettato, è la strada da percorrere. Ma per un singolo caso rapido, questa alternativa potrebbe essere più semplice.

Fonte

: https://github.com/plataformatec/responders/pull/115#issuecomment-72517532

1

Non è un grande fan di questo comportamento. Per aggirare l'ostacolo, ho dovuto evitare di utilizzare il metodo di respond_with:

class SomeController < ApplicationController 
    respond_to :json 

    def update 
    # ... 
    respond_to do |format| 
     format.json { render(json: some_object, status: 200) } 
    end 
    end 
end 
Problemi correlati