2011-09-05 7 views
16

Sto costruendo una semplice API json in Rails 3.1. Ho creato un controller che ha due funzioni:I binari rispondono_con recitazione diversa nell'indice e creano il metodo

class Api::DogsController < ActionController::Base 
    respond_to :json, :xml 
    def index 
    respond_with({:msg => "success"}) 
    end 

    def create 
    respond_with({:msg => "success"}) 
    end 
end 

In routes.rb ho

namespace :api do 
    resources :dogs 
end 

Quando faccio una richiesta GET a http://localhost:3000/api/dogs ottengo il JSON corretta dall'alto. Quando faccio un post allo stesso URL, ottengo un'eccezione rotaie:

ArgumentError in Api::DogsController#create 
Nil location provided. Can't build URI. 
actionpack (3.1.0) lib/action_dispatch/routing/polymorphic_routes.rb:183:in `build_named_route_call` 
actionpack (3.1.0) lib/action_dispatch/routing/polymorphic_routes.rb:120:in `polymorphic_url' 
actionpack (3.1.0) lib/action_dispatch/routing/url_for.rb:145:in `url_for' 

Ma se cambio il codice creare per

def create 
    respond_with do |format| 
    format.json { render :json => {:msg => "success"}} 
    end 
end 

restituisce il JSON bene.

Qualcuno può spiegare cosa sta succedendo qui?

risposta

38

Dopo aver riscontrato questo problema e averlo superato, credo di poter fornire una risposta.

Quando si dice semplicemente:

def create 
    respond_with({:msg => "success"}) 
end 

Cosa rotaie cerca di fare è "indovinare" un URL che la risorsa appena creata è disponibile presso, e posizionarlo nella HTTP location header. Tale ipotesi fallisce miseramente per un oggetto hash (la posizione che deduce è nulla, che porta al messaggio di errore che si sta vedendo).

Per superare questo problema, allora, si avrebbe bisogno di fare quanto segue:

def create 
    respond_with({:msg => "success"}, :location => SOME_LOCATION) 
end 

Supponendo che si sa dove si trova la nuova risorsa. Puoi anche specificare "nil" come "SOME_LOCATION" e questo funzionerà (in modo un po 'assurdo).

+1

Impostazione posizione letterale stringa "nil" ha funzionato: 'reply_with ({: error =>" bad "},: status => 401,: location =>" nil ")' –

+0

@kwbeam stavo parlando di un valore attuale nullo nell'ultimo paragrafo (mi rendo conto ora che le virgolette potrebbero essere state un po 'fuorvianti) – Aubergine

+0

Pensavo volessi dire nil l'oggetto, non la stringa letterale, ma quando l'ho provato, non ha funzionato. Tuttavia, ho appena cambiato di nuovo a zero (l'oggetto, non la stringa letterale) e sta funzionando. Quindi a quanto pare ho avuto un fallimento da qualche parte, ma non sono in grado di ricostruire quello che ho fatto di sbagliato. Dispiace per la confusione. (Avevo aggiornato la versione di Rails e molte gemme nel frattempo, quindi forse c'era un bug che veniva corretto ... ma non sono sicuro) –

1

Ho avuto il problema da solo.

È, come dice Aubergine, qualcosa correlato all'intestazione della posizione http.

In realtà, le guide sembrano costruire questa posizione utilizzando per impostazione predefinita show route.

Se non si dispone di un show action, -che è strano in un'API, ma può succedere (credo) `, quindi è necessario impostare una posizione da soli. Non ho idea di quale sia lo standard in questo caso.

Se accade che è necessario un percorso di presentazione, quindi codificarlo e tutto dovrebbe funzionare correttamente.

Cheers.

0

Ho scoperto che errori = {: errore => @ device.errors.full_messages} respond_with (errori,: Stato =>: bad_request,: location => nil) opere. L': location è richiesto e impostandolo a zero aiuta quando si utilizza con spec: si aspettano (last_response.status) .not_to eql 201 aspettano (last_response.location) .to be_nil

Il problema che stavo avendo è che ero non restituire l'hash degli errori, solo lo stato. Aggiungendo l'hash degli errori e impostando il luogo io stesso l'ho risolto.

Problemi correlati