Rails respond_with: come funziona?


128

Ho letto qua e là su quanto sia bello il respond_withmetodo in Rails 3. Ma non riesco nemmeno a trovare un riferimento ad esso nelle API di Rails o cercando l'origine. Qualcuno può spiegarmi come funziona (quali opzioni è possibile utilizzare, ecc.) Oppure indicarmi il luogo in cui è effettivamente implementato in modo da poter esaminare il codice da solo?

Risposte:


128

Aggiornamento per Rails 4.2+

#respond_withe ::respond_to( metodo della classe nb ) non fanno più parte di Rails . Sono stati migrati nella gemma di responder di terze parti a partire da Rails 4.2 ( note di rilascio / commit datato agosto 2014). Sebbene i risponditori non siano inclusi in Rails per impostazione predefinita, è una dipendenza di Devise e quindi disponibile in molte applicazioni Rails.

Il #respond_to metodo di istanza, tuttavia, fa ancora parte di Rails (5.2rc1 al momento della stesura).

La documentazione ufficiale dell'API di Rails per ActionController::MimeRespondsspiega come #respond_tofunziona. I commenti della documentazione di Rails Guides originali per #respond_withe ::respond_topossono ancora essere trovati nel codice sorgente gem dei rispondenti .


Risposta originale

Il codice per i responder si basa su una classe e un modulo. MimeResponds incluso in ActionController :: Base , la classe ApplicationControllerda cui erediti. Quindi c'è ActionController :: Responder che fornisce il comportamento predefinito quando si utilizza respond_with.


Per impostazione predefinita, l'unico comportamento fornito dalle guide nella risposta è un tentativo implicito di eseguire il rendering di un modello con un nome corrispondente all'azione. Qualunque cosa oltre a ciò richiede ulteriori istruzioni all'interno dell'azione o una risposta personalizzata per chiamare con un blocco per gestire le risposte a più formati.

Poiché la maggior parte dei controller utilizza un modello di personalizzazione abbastanza comune, i responder forniscono un ulteriore livello di astrazione introducendo un comportamento più predefinito. Leggi le azioni che chiamano to_xml / to_json per formati specifici e le azioni del mutatore che forniscono lo stesso e i reindirizzamenti per azioni del mutatore riuscite.


Ci sono alcune opportunità per personalizzare il comportamento dei soccorritori, dalle sottili modifiche alla completa sostituzione o estensione del comportamento.

Livello di classe: respond_to

Qui si specificano i formati che il risponditore dovrebbe gestire. I formati possono essere personalizzati su quali azioni verranno applicate. Ogni formato può essere specificato con chiamate separate, consentendo la completa personalizzazione delle azioni per ciascun formato.

# Responds to html and json on all actions
respond_to :html, :json

# Responds to html and json on index and show actions only.
respond_to :html, :json, :only => [:index,:show]

# Responds to html for everything except show, and json only for index, create and update
respond_to :html, :except => [:show]
respond_to :json, :only => [:index, :create, :update]

Livello di classe: responder

Questo è un attributo di classe che contiene il risponditore. Questo può essere tutto ciò che risponde alla chiamata, il che significa che puoi usare un proc / lambda o una classe che risponde alla chiamata. Un'altra alternativa è quella di mescolare uno o più moduli al risponditore esistente per sovraccaricare i metodi esistenti, aumentando il comportamento predefinito.

class SomeController < ApplicationController
  respond_to :json

  self.responder = proc do |controller, resources, options|
    resource = resources.last
    request = controller.request
    if request.get?
      controller.render json: resource
    elsif request.post? or request.put?
      if resource.errors.any?
        render json: {:status => 'failed', :errors => resource.errors}
      else
        render json: {:status => 'created', :object => resource}
      end
    end
  end
end

Mentre ci possono essere alcuni casi interessanti di utilizzo dei bordi, è più probabile che l'estensione o la miscelazione dei moduli nel risponditore predefinito siano schemi più comuni. In ogni caso, le opzioni rilevanti sono le risorse e le opzioni, in quanto passano dalla from respond_with.

Livello di istanza: respond_with

Le opzioni qui sono quelle che verrebbero passate per renderizzare o redirect_to nel tuo controller, ma sono incluse solo per scenari di successo. Per le azioni GET queste sarebbero le chiamate di rendering, per altre azioni queste sarebbero le opzioni per il reindirizzamento. Probabilmente la più utile di queste è l' :locationopzione, che può essere utilizzata per sovrascrivere quel percorso di reindirizzamento nel caso in cui gli argomenti per respond_with non siano sufficienti per creare l'URL giusto.

# These two are essentially equal
respond_with(:admin, @user, @post)
respond_with(@post, :location => admin_user_post(@user, @post)

# Respond with a 201 instead of a 200 HTTP status code, and also
# redirect to the collection path instead of the resource path
respond_with(@post, :status => :created, :location => posts_path)

# Note that if you want to pass a URL with a query string
# then the location option would be needed.
# /users?scope=active
respond_with(@user, :location => users_path(:scope => 'active'))

In alternativa, la gemma del responder non fornisce solo alcuni moduli per sovrascrivere alcuni dei comportamenti predefiniti. Sostituisce il risponditore predefinito con una classe anonima che estende il risponditore predefinito e fornisce un metodo a livello di classe per mescolare moduli personalizzati a questa classe. Il più utile qui è il flash responder, che fornisce un set predefinito di flash, delegando la personalizzazione al sistema I18n, config/locales/en.ymlper impostazione predefinita.

Alcuni esempi di risponditori personalizzati che ho usato in progetti precedenti includono un risponditore che ha decorato automaticamente le mie risorse e fornito un set predefinito di titoli di pagina con un'interfaccia per personalizzare o sovrascrivere facilmente il titolo della pagina.


1
Penso che intendi (nel corpo della classe) self.responder =come responder =assegnerai ad un locale
Horseyguy,

Grazie! L'esistenza locationdell'opzione era l'informazione di cui avevo bisogno!
JellicleCat,

1
Questa spiegazione è ancora pertinente per Rails 4/5? Ho sentito che respond_withsarebbe deprecato, ma non riesco a scoprire perché.
Arnlen,

1
@Arnlen, respond_with è stato estratto come gemma separata " responder "
Nick Roz,

Nota che per far funzionare i flash config/locales/en.yml, è necessario responders :flashnella parte superiore del controller.
bjnord,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.