Rails 3: il paradigma RESTful

16 febbraio 2010

More REST in Rails

Rails 3.0 apporta alcune sostanziali modifiche alla sintassi di routes e renders; lo scopo è quello di sfruttare ancora di più le convenzioni insite nel paradigma RESTful per ridurre le linee di codice necessarie. Capita spesso infatti che, scrivendo un applicazione con Rails 2.x, quasi ogni azione di ogni controller si concluda con un respond_to più o meno complesso, come nell’esempio seguente:

def index
  @users = User.all
  respond_to do |format|
    format.html
    format.xml { render :xml => @users }
    format.json { render :json => @users }
  end
end

Per ovviare a questo la nuova versione del framework introduce il metodo respond_with che non fa altro che applicare un comportamento convenzionale basandosi su alcuni fattori quali il verbo con cui è stata fatta la richiesta, la presenza o meno di errori, il tipo di formato di output richiesto, etc. Ad esempio il codice esposto poc’anzi si traduce in:

def index
  @users = User.all
  respond_with(@users)
end

mentre un’azione di creazione classica può essere implementata in questo modo:

def create
  @user = User.new(params[:user])
  flash[:notice] = 'Utente creato correttamente' if @user.save
  respond_with(@user)
end

Notate come le due chiamate che concludono le due funzioni siano esattamente le stesse: respond_with(@user); la magia avviene infatti all’interno della classe ActionController::Responder, invocata dalla funzione respond_with, dove metodi specifici per ogni formato intervengono utilizzando convenzioni per stabilire la corretta reazione a fronte delle informazioni disponibili. Prendiamo per esempio il classico formato HTML e ispezioniamone il funzionamento:

def to_html
    default_render
  rescue ActionView::MissingTemplate => e
    navigation_behavior(e)
end

def navigation_behavior(error)
  if get?
    raise error
  elsif has_errors? && default_action
    render :action => default_action
  else
    redirect_to resource_location
  end
end

la funzione to_html tenta in primis di eseguire il template associato all’azione corrente, se fallisce (ad esempio perchè non esiste un template, come nelle azioni di create) invoca la funzione navigation_behavior che si comporta nel seguente modo:

  • se il verbo di chiamata è GET viene lanciata un eccezione (in quanto ogni azione chiamata in get dovrebbe tradursi nel rendering di un template a video)
  • se invece ci sono degli errori all’interno della risorsa (nel nostro caso @user) viene effettuato il render dell’azione di default (edit.html.erb per il verbo PUT e new.html.erb per il POST)
  • nel caso in cui nessuna delle due condizioni precedenti sia soddisfatta lo script esegue un redirect verso l’azione index del controller corrente

Chiaramente è possibile modificare questa convenzione, ad esempio operando come nell’esempio seguente, che riprende il codice scritto in precedenza forzando però il redirect verso una pagina a nostro piacere (nel caso di formato HTML):

def create
  @user = User.new(params[:user])
  flash[:notice] = 'Utente creato correttamente' if @user.save
  respond_with(@user) do |format|
    format.html { redirect_to users_url }
  end
end

Se vuoi aggiornamenti su Rails 3: il paradigma RESTful inserisci la tua e-mail nel box qui sotto:
 
X
Se vuoi aggiornamenti su Rails 3: il paradigma RESTful

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy