Anzeige
Anzeige
UX & Design
Artikel merken

Teil 2: Die Praxis der REST-Architektur in Ruby On Rails: REST in Rails

Rails 1.2 bringt als große Neuerung die Unterstützung der REST-Architektur mit sich. Nachdem sich Teil 1 (siehe T3N Magazin Nr. 7) um die theoretischen Hintergründe von REST drehte, geht es nun ans Eingemachte: Eine kleine Artikel-Verwaltung soll RESTful umgesetzt werden.

6 Min. Lesezeit
Anzeige
Anzeige

Die REST-basierte Entwicklung in Rails bietet nur wenige Unterschiede zur „klassischen“, altbekannten Vorgehensweise. Neu sind vor allem folgende Punkte:

  • respond_to im Controller ermöglicht es, mit wenigen Handgriffen unterschiedliche Response-Formate auszugeben.
  • Das Routing erhält mit der Methode „resources“ eine REST-Implementierung.
  • Redirects im Controller und Links in den Views verfügen über neue Methoden und Helper.
Anzeige
Anzeige

Über diese größeren Neuerungen hinaus bleibt uns aber größerer Lernaufwand erspart – die meisten anderen Bereiche werden durch REST nicht berührt. Daher werden in diesem Artikel auch nur die entscheidenden, neuen Bereiche angesprochen.

Auf die Plätze… fertig… coden!

Wie bei jedem Rails-Projekt sind auch hier die ersten Schritte das Generieren des Anwendungs-Codes über „rails projektname“ und das Anlegen der entsprechenden Datenbank(en).

Anzeige
Anzeige

Interessant wird es, wenn wir nun den neuen Script-Generator „scaffold_resource“ einsetzen, um uns ein Grundgerüst bestehend aus Model, Controller und allem was dazu gehört erzeugen zu lassen. Der Generator erwartet als ersten Parameter den Namen des Models. Aus dem Namen des Models generiert Rails automatisch dann auch den entsprechenden Controller: Der Plural des Models wird hierfür als Name verwendet.

Anzeige
Anzeige

Weitere Parameter erlauben es uns, in der zugehörigen Datenbank-Migration gleich bestimmte Felder anlegen zu lassen und in der View ebenfalls diese Felder zu nutzen. In unserem Beispiel legen wir das Model „article“ mitsamt den Tabellenfeldern title, category, teaser, keywords, date und content sowie den Controller „articles_controller“ an. Dazu genügt folgender Befehl:

Ruby On Rails
$ ruby script/generate scaffold_resource article title:string teaser:text keywords:string date:date content:text

Listing 1

Mit „rake db:migrate“ wird nun die Datenbanktabelle auch tatsächlich inklusive der gewünschten Felder angelegt. Ein Blick in den generierten Code gibt uns zwei interessante Auskünfte:

Anzeige
Anzeige
  1. Im Hinblick auf die Models bringt der REST-Ansatz nichts Neues mit sich.
  2. Im Hinblick auf den Controller allerdings schon (hierzu später mehr).

Starten wir doch kurz unseren Server (ab Rails 1.2 übrigens standardmäßig Mongrel und nicht mehr WEBrick):

Ruby On Rails
$ ruby script/server

Listing 2

Nun schicken wir unseren Browser auf die Adresse http://localhost:3000/articles – Sie werden sehen, dass sich alles anfühlt, wie bei einer Rails-Anwendung ohne REST auch. Alles – bis auf die URLs und den dahinterliegenden Code.

Erinnern Sie sich: Bei REST wird die Action nun über das verwendete HTTP-Verb bestimmt und kommt daher nicht mehr in der URL vor. Bis auf die Ausnahmen new und edit enthalten unsere CRUD-URLs jetzt also nur noch den Controller und die ID des Datensatzes und sehen damit alle folgendermaßen aus:

Anzeige
Anzeige
URL
http://localhost:3000/articles/1

Listing 3

Um nun zu beurteilen, was durch diesen Aufruf passiert, reicht ein Blick auf die URL nicht aus. Erst die verwendete HTTP-Methode gibt Auskunft darüber, was mit der Ressource geschieht:

Aktion URL HTTP-Methode Link-Helper
index /articles GET articles_path
show /articles/1 GET article_path(1)
new /articles/new GET new_article_path
edit /articles/1;edit GET edit_article_path(1)
create /articles POST articles_path
update /articles/1 PUT article_path(1)
destroy /articles/1 DELETE article_path(1)

Kreative Namensgeber werden nun vielleicht enttäuscht sein: keine abwechslungsreichen URLs wie /articles/add_new_article oder /articles/delete_article/1 mehr. Dafür werden Sie aber mit einem einheitlichen Set an URL-Standards belohnt, das von Applikation zu Applikation konstant bleibt.

Ein Problem gilt es noch zu lösen (das übernimmt allerdings netterweise Rails für uns): Aktuelle Browser unterstützen nur die klassischen HTTP-Methoden GET und POST. Daher muss das Framework hier etwas nachhelfen, um eine massenkompatible Lösung zu schaffen.

Anzeige
Anzeige

Diese Lösung sieht folgendermaßen aus: Auch Rails verwendet hinter den Kulissen lediglich die beiden Klassiker GET und POST. Die Helper-Methoden, die die neuen REST-Links erstellen, simulieren die HTTP-Verben PUT und DELETE über versteckte Formularfelder. Ein Link zum Löschen einer Ressource wird von Rails so mit JavaScript versehen, dass beim Absenden daraus ein über POST versendetes Formular wird, das ein hidden field mit dem Namen „_method“ und dem Wert „delete“ enthält. Kommt dieser Request bei unserer Rails-Anwendung an, weiß sie dadurch automatisch, dass es sich „eigentlich“ um einen DELETE-Request handeln soll.

Was hat sich nun im Code des Controllers verändert? Vor allem die Möglichkeit, sehr einfach unterschiedliche Ausgabeformate liefern zu können, macht REST so attraktiv. Über den respond_to-Block ist dies schnell und im Idealfall ohne duplizierten Code realisierbar:

Ruby On Rails
 # GET /articles/1
 # GET /articles/1.xml
  def show
     @article = Article.find(params[:id])
     respond_to do |format|
        format.html # show.rhtml
        format.xml  { render :xml => @article.to_xml }
     end
  end

Listing 4

Die Entscheidung, welches Format nun tatsächlich an den Client zurückgegeben wird, kann über zwei verschiedene Wege getroffen werden: Entweder das Accept-Feld des HTTP-Headers gibt vor, welche Art Content der Client wünscht oder die URL des Requests enthält das Format explizit (z. B. durch /articles.xml).
Um unsere Anwendung nun zum Beispiel auch Daten im JSON-Format ausgeben zu lassen, brauchen wir nur folgende Zeile in den respond_to-Block der show-Methode einzufügen:

Anzeige
Anzeige
Ruby On Rails
respond_to-Block in app/controllers/articles_controller.rb
format.json { render :json => @article.to_json }

Listing 5

link_to & Co.

Im View-Code gibt es eine weitere Neuheit: link_to wurde mit einigen REST-spezifischen Helper-Methoden aufpoliert:

link_to in Views, z. B. app/views/articles/index.rhtml
<%= link_to 'Show', article_path(article) %>	# /articles/1
<%= link_to 'Edit', edit_article_path(article) %>	# /articles/1;edit
<%= link_to 'Destroy', article_path(article), :confirm => 'Are you sure?', :method => :delete %>
	# /articles/1   - allerdings mit JavaScript-Zusätzen, um die HTTP-Methode DELETE mitzugeben

Listing 6

Anstatt wie in klassischen Applikationen :controller-, :action- und :id-Parameter an link_to zu übergeben, können jetzt die *_path-Methoden verwendet werden. Im obigen Code-Beispiel wird auch deutlich, wie die PUT und DELETE-Requests zustande kommen – nämlich durch den Parameter :method.

Insgesamt sind es sieben neue Standard-Path-Methoden, die Rails für uns erstellt hat – eine für jede der sieben REST-Aktionen. In der Tabelle auf der vorigen Seite sind sie neben der jeweiligen Aktion aufgeführt.

Anzeige
Anzeige

Mit den *_path-Methoden werden gleichzeitig auch neue Helper-Methoden für die Verwendung im Controller generiert. Sie sind identisch zu den _path-Methoden, außer dass sie auf _url enden (z. B. articles_url statt articles_path). Diese Helper werden klassischerweise dann verwendet, wenn es darum geht, der redirect_to-Methode ein Ziel zu geben.

app/controllers/articles_controller.rb
format.html { redirect_to article_url(@article) }

Listing 7

Neues Routing

Doch wo kommen diese scheinbar von Geisterhand erzeugten neuen Helper-Methoden überhaupt her? Das Routing von REST-Applikationen ist ebenfalls neu und generiert uns netterweise all diese _path- und _url-Methoden:

config/routes.rb
ActionController::Routing::Routes.draw do |map|
     map.resources :articles
     ....
end

Listing 8

Eigene Actions und Helpers anlegen

Die REST-Implementierung in Rails unterstützt standardmäßig die klassischen CRUD-Actions (Create, Read, Update, Delete). Doch in den meisten Anwendungen müssen darüber hinaus weitere Funktionen verfügbar sein. Diese müssen einerseits als Actions im Controller angelegt werden, andererseits muss aber auch das Routing auf diese neuen, für Rails unbekannten Actions eingestellt werden, damit die Applikation weiß, wie sie auf eine bisher unbekannte URL reagieren soll. In config/routes.rb muss daher ein neuer Eintrag für jede neue Action angelegt werden:

Anzeige
Anzeige
config/routes.rb
map.resources :articles, :member => {:bsp_action => :get}

Listing 9

Der :member-Parameter erwartet einen Hash, der Rails sagt, welche Action über welche HTTP-Methode (:get, :post, :delete, :put oder :any) erwartet wird. Außer :member kann auch :collection (für Actions, die statt mit einer einzigen Ressource mit mehreren arbeiten) und :new (Actions, die neue Ressourcen anlegen) zum Einsatz kommen. Dieser neue map.resources-Eintrag generiert dann die erforderlichen Routes und Helper-Methoden:

Action-Name URL Helper-Methode HTTP
bsp_action /articles;bsp_action bsp_action_articles_url GET

Wird dann beispielsweise dieser Request über POST abgesendet, erhalten wir einen Routing-Error. Denn in unserer routes.rb haben wir definiert, dass die Action nur über GET aufgerufen werden soll.

Ausblick auf Rails 2.0

Rails 2.0 wird eine kleine Änderung in den Naming Conventions bei den REST-URLs mit sich bringen. Die Verwendung des Semikolons, wie zum Beispiel in „article/1;edit“, wird zugunsten der weniger gewöhnungsbedürftigen Schreibweise „article/1/edit“ aufgegeben. Hartcodierte Links sollten also am besten nicht mehr das Semikolon nutzen, da map.resources dies in Rails 2.0 nicht mehr unterstützen wird.

Mehr zu diesem Thema
Fast fertig!

Bitte klicke auf den Link in der Bestätigungsmail, um deine Anmeldung abzuschließen.

Du willst noch weitere Infos zum Newsletter? Jetzt mehr erfahren

Anzeige
Anzeige
Schreib den ersten Kommentar!
Bitte beachte unsere Community-Richtlinien

Wir freuen uns über kontroverse Diskussionen, die gerne auch mal hitzig geführt werden dürfen. Beleidigende, grob anstößige, rassistische und strafrechtlich relevante Äußerungen und Beiträge tolerieren wir nicht. Bitte achte darauf, dass du keine Texte veröffentlichst, für die du keine ausdrückliche Erlaubnis des Urhebers hast. Ebenfalls nicht erlaubt ist der Missbrauch der Webangebote unter t3n.de als Werbeplattform. Die Nennung von Produktnamen, Herstellern, Dienstleistern und Websites ist nur dann zulässig, wenn damit nicht vorrangig der Zweck der Werbung verfolgt wird. Wir behalten uns vor, Beiträge, die diese Regeln verletzen, zu löschen und Accounts zeitweilig oder auf Dauer zu sperren.

Trotz all dieser notwendigen Regeln: Diskutiere kontrovers, sage anderen deine Meinung, trage mit weiterführenden Informationen zum Wissensaustausch bei, aber bleibe dabei fair und respektiere die Meinung anderer. Wir wünschen Dir viel Spaß mit den Webangeboten von t3n und freuen uns auf spannende Beiträge.

Dein t3n-Team

Melde dich mit deinem t3n Account an oder fülle die unteren Felder aus.

Bitte schalte deinen Adblocker für t3n.de aus!
Hallo und herzlich willkommen bei t3n!

Bitte schalte deinen Adblocker für t3n.de aus, um diesen Artikel zu lesen.

Wir sind ein unabhängiger Publisher mit einem Team von mehr als 75 fantastischen Menschen, aber ohne riesigen Konzern im Rücken. Banner und ähnliche Werbemittel sind für unsere Finanzierung sehr wichtig.

Schon jetzt und im Namen der gesamten t3n-Crew: vielen Dank für deine Unterstützung! 🙌

Deine t3n-Crew

Anleitung zur Deaktivierung
Artikel merken

Bitte melde dich an, um diesen Artikel in deiner persönlichen Merkliste auf t3n zu speichern.

Jetzt registrieren und merken

Du hast schon einen t3n-Account? Hier anmelden

oder
Auf Mastodon teilen

Gib die URL deiner Mastodon-Instanz ein, um den Artikel zu teilen.

Anzeige
Anzeige