Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Geleitwort des Fachgutachters
Einleitung
1 Einführung
2 Installation
3 Erste Schritte
4 Einführung in Ruby
5 Eine einfache Bookmarkverwaltung
6 Test-Driven Development
7 Rails-Projekte erstellen
8 Templatesystem mit ActionView
9 Steuerzentrale mit ActionController
10 Datenbankzugriff mit ActiveRecord
11 E-Mails verwalten mit ActionMailer
12 Nützliche Helfer mit ActiveSupport
13 Ajax on Rails
14 RESTful Rails und Webservices
15 Rails mit Plug-ins erweitern
16 Performancesteigerung
17 Sicherheit
18 Veröffentlichen einer Rails-Applikation auf einem Server
Ihre Meinung?

Spacer
 <<   zurück
Ruby on Rails 2 von Hussein Morsy, Tanja Otto
Das Entwickler-Handbuch
Buch: Ruby on Rails 2

Ruby on Rails 2
geb., mit DVD
699 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-89842-779-1
Online bestellenPrint-Version Jetzt Buch bestellen
* versandkostenfrei in (D) und (A)
Pfeil 14 RESTful Rails und Webservices
  Pfeil 14.1 Was sind Webservices?
  Pfeil 14.2 REST
  Pfeil 14.3 RESTful Rails
  Pfeil 14.4 Einen Webservice anbieten
  Pfeil 14.5 Zugriff auf einen Webservice mit ActiveResource


Rheinwerk Computing - Zum Seitenanfang

14.3 RESTful Rails  Zur nächsten ÜberschriftZur vorigen Überschrift

Vorteile

Der Einsatz des REST-Standards in Rails wird als RESTful Rails bezeichnet.

Wenn Sie Ihre Applikationen nach dem REST-Standard entwickeln, bietet das u. a. folgende Vorteile:

  • URLs sind vereinfacht.
  • URLs sind standardisiert.
  • Realisierung eines Webservices bzw. einer API ist praktisch ohne Mehraufwand möglich.

Rails macht es Ihnen sehr leicht, Websites nach dem REST-Standard zu erstellen. Am einfachsten ist es, wenn Sie Generatoren einsetzen.


Rheinwerk Computing - Zum Seitenanfang

Generatoren  Zur nächsten ÜberschriftZur vorigen Überschrift

Es gibt zwei Generatoren, die Sie beim Implementieren des REST-Standards unterstützen:

  • scaffold-Generator
    Der scaffold-Generator erzeugt neben einem Model und der Migration- Datei für die Erstellung der Datenbanktabelle auch einen Controller mit sieben Actions und die passenden Views, um die Datensätze zu verwalten (Anzeigen, Hinzufügen, Ändern und Löschen).
    ruby script/generate scaffold airport name:string \
    code:string
          ...
          create  app/views/airports/index.html.erb
          create  app/views/airports/show.html.erb
          create  app/views/airports/new.html.erb
          create  app/views/airports/edit.html.erb
          create  app/views/layouts/airports.html.erb
          create  public/stylesheets/scaffold.css
          create  app/models/airport.rb
          create  test/unit/airport_test.rb
          create  test/fixtures/airports.yml
          create  db/migrate
          create  db/migrate/001_create_airports.rb
          create  app/controllers/airports_controller.rb
          create  test/functional/airports_controller_test.rb
          create  app/helpers/airports_helper.rb
           route  map.resources :airports
  • resource-Generator

    Der resource -Generator macht im Prinzip das Gleiche wie der scaffold -Generator, jedoch mit dem Unterschied, dass keine Views erstellt werden und der Controller keine Actions (Methoden) enthält.

    ruby script/generate resource airport name:string \
    code:string
          ...
          create app/views/airports
          create app/models/airport.rb
          create test/unit/airport_test.rb
          create test/fixtures/airports.yml
          create db/migrate
          create db/migrate/001_create_airports.rb
          create app/controllers/airports_controller.rb
          create test/functional/airports_controller_test.rb
          create app/helpers/airports_helper.rb
           route map.resources :airports

Rheinwerk Computing - Zum Seitenanfang

Ressourcen  Zur nächsten ÜberschriftZur vorigen Überschrift

routes.rb

Beide Generatoren fügen in der Routing-Konfigurationsdatei routes.rb im Verzeichnis config folgenden Eintrag ein:

Listing  config/routes.rb

map.resources :airports

Aufgrund dieses Routing-Eintrages sind folgende Zugriffe auf die Ressource airports möglich:

  • GET /airports
    Es wird der AirportsController mit der Action index aufgerufen. Diese Action listet alle Flughäfen. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Alle Airports', airports_path+
  • GET /airports/1
    Es wird der AirportsController mit der Action show und dem Parameter id = 1 aufgerufen. Diese Action zeigt den Flughafen mit der angegebenen ID an. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Airport Detail', airport_path(1)
  • GET /airports/new
    Es wird der AirportsController mit der Action new aufgerufen. Diese Action lädt das Formular zum Anlegen eines Airports. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'neuer Airport', new_airport_path
  • GET /airports/1/edit
    Es wird der AirportsController mit der Action edit aufgerufen. Diese Action lädt das Formular zum Bearbeiten eines Airports. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Airport editieren', edit_airport_path(1)
  • POST /airports
    Es wird der AirportsController mit der Action create aufgerufen. Diese Action erstellt einen neuen Airport-Datensatz. Der Aufruf erfolgt über ein Formular:
    form_for(@airport) do ... end
    Die HTTP-Methode muss nicht angegeben werden, da sie automatisch erkannt wird. Wenn das Objekt @airport neu ist, wird die POST-Methode verwendet.
  • PUT /airports/1
    Es wird der AirportsController mit der Action update aufgerufen. Diese Action ändert die Daten des angegebenen Airport-Datensatzes. Der Aufruf erfolgt über ein Formular:
    form_for(@airport) do ... end
    Die HTTP-Methode muss nicht angegeben werden, da sie automatisch erkannt wird. Wenn das Objekt @airport bereits in der Datenbank vorliegt, wird automatisch die PUT-Methode ausgeführt.
  • DELETE /airports/1
    Es wird der AirportsController mit der Action destroy aufgerufen. Diese Action löscht den angegebenen Datensatz. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to "löschen", airport_path(1), :method => :delete

Zugriff auf ID

Da per Konvention immer auf die ID eines Objektes zugegriffen wird, wenn das ganze Objekt übergeben wird, können wir statt der IDs auch das Objekt airport in die Methoden übergeben:

airport_path(airport)

edit_airport_path(airport)
Standard-Routing deaktivieren
Wenn Sie nur Ressourcen einsetzen, ist es empfehlenswert, das Standard-Routing zu deaktivieren. Kommentieren Sie dazu die folgenden Zeilen aus der config/routes.rb aus:
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'


Rheinwerk Computing - Zum Seitenanfang

Verschachtelte Ressourcen  Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn eine Ressource von einer anderen Ressource abhängig ist, kann eine verschachtelte Ressource angelegt werden. Angenommen, wir wollten zu den Flughäfen die Ladenlokale (shops) verwalten, können wir mit dem scaffold -Generator eine Model-Klasse mit zugehörigem Controller und Formularen erstellen:

ruby script/generator scaffold shop name:string ...

Da es zu einem Flughafen mehrere Shops geben kann, besteht eine Eins-zu-viele-Relation(siehe Kapitel 10). Interessant ist, dass diese Abhängigkeit auch in der URL abgebildet werden kann.

has_many

Dazu wird die Abhängigkeit wie folgt im Routing festgelegt:

Listing  config/routes.rb

map.resources :airports, :has_many => :shops

Der Zugriff auf die Ressource shops erfolgt dann wie folgt:

  • GET http://localhost:3000/airports/2
    Es wird im Airports-Controller die Action show mit dem Parameter id=2 aufgerufen. Im View kann der Aufruf wie folgt erfolgen:
    link_to 'Airport Detail', airport_path(2)
  • GET http://localhost:3000/airports/2/shops
    Es wird im Shops-Controller die Action index mit dem Parameter airport_id=2 aufgerufen. Im View kann der Aufruf wie folgt erfolgen:
    link_to 'Alle Shops vom Flughafen 2',
    airport_shops_path(:airport_id=>2)
  • DELETE http://localhost:3000/airports/2/shops/5
    Es wird im Shops-Controller die Action destroy mit den Parametern id=5 und airport_id=2 aufgerufen. Im View kann der Aufruf wie folgt erfolgen:
    link_to 'Zeige Shop 5 vom Flughafen 2',
    airport_shop_path(:airport_id=>2, :id=>5)
  • usw.

Mehrere Verschachtelungen

Es können in einem Routing-Eintrag auch mehrere Verschachtelungen definiert werden. Ein Flughafen kann nicht nur mehrere Shops, sondern auch mehrere Restaurants haben. Der Routing-Eintrag könnte dann wie folgt aussehen:

map.resources :airports, :has_many => [:shops, :restaurants]

has_one

Eine Abhängigkeit mit einer Singleton-Ressource (siehe Abschnitt 14.3.5) kann mit der :has_one -Option definiert werden. In der folgenden Routing-Regel wird jedem Airport ein Direktor zugeordnet:

map.Ressource :airports, :has_one => :director

Rheinwerk Computing - Zum Seitenanfang

Namespaces  Zur nächsten ÜberschriftZur vorigen Überschrift

Rails 2.0

Namespaces ist eine neue Funktion von Rails 2.0, die in der Praxis eine hohe Relevanz hat.

Normalerweise gehört zu einer Model-Klasse (z. B. Airport) genau einen Controller (Airports-Controller). Dieser Controller dient dann in der Regel zum Verwalten der Daten. Man kann auch sagen, dass dieser Controller für die Administratoren (oder Redakteure) der Website bestimmt ist. Für die Anzeige der Flughäfen für den Endbenutzer ist ein weiterer Controller erforderlich, der sich auf das gleiche Model bezieht.

Die beiden Controller sollten wie folgt aufgerufen werden können:

  • http://localhost:3000/admin/airports
    Auf dieser Seite können die Flughäfen verwaltet werden. Es werden alle Flughäfen angezeigt. Zu jedem Datensatz werden Links zum Ändern und Löschen angezeigt. Diese Seite sollte passwortgeschützt sein.
  • http://localhost:3000/airports
    Diese Seite ist für den Endbenutzer bestimmt. Es werden z. B. alle Flughäfen gelistet. Jedoch soll das Editieren und Löschen der Datensätze nicht möglich sein.

Um dies zu erreichen, sind folgende Schritte erforderlich:

  1. Generieren der Model-Klasse und dem Admin-Controller

    Dem Namen des Models muss admin/ vorangestellt werden. Der Airports- Controller wird dann im Verzeichnis app/controllers/admin abgelegt.

    ruby script/generate scaffold
    admin/ airport code:string \
    name:string

    Die Model-Klasse Airport wird jedoch wie gewohnt im Verzeichnis app/models abgelegt. Mit rake db:migrate führen Sie die Migration-Datei aus, um die Tabelle airports in der Datenbank zu erstellen.

  2. Generieren des Controllers für den Endbenutzer

    Für den Endbenutzer kann man nun einen weiteren Controller anlegen, der z. B. nur die Flüge auflisten (Action index) und zu einem Flug die Details anzeigen kann (Action show).

    Hierfür verwenden wir nicht den scaffold -Generator, sondern lediglich den controller -Generator.

    ruby script/generate controller airports index show

    Plural verwenden

    Beachten Sie, dass Sie unbedingt die Pluralform von »Airport« verwenden. Der controller -Generator erstellt für uns leere Actions und leere Templates, die noch ausprogrammiert bzw. angelegt werden müssen. Wir könnten im Controller z. B. Folgendes eintragen:

    Listing  app/controllers/airport

    class AirportsController < ApplicationController
      def index
        @airports = Airport.find(:all)
      end
    
      def show
        @airport = Airport.find(params[:id])
      end
    end

    Zusätzlich müssen noch die Template-Dateien mit Inhalten gefüllt werden.

  3. Routing-Eintrag

    In der Routing-Datei config/routes.rb benötigen wir einen Routing-Eintrag für den Endbenutzer-Controller und einen für den Admin-Controller:

    map.resources :airports
    
    map.namespace(:admin) do |admin|
      admin.resources :airports
    end

Zur Verlinkung der Seiten kann im View dann z. B. folgender Aufruf eingesetzt werden:

<%= link_to "Airport-Liste", airports_path %>

<%= link_to "Airport-Administration", admin_airports_path %>

Rheinwerk Computing - Zum Seitenanfang

Singleton-Ressourcen  Zur nächsten ÜberschriftZur vorigen Überschrift

Anwendung

Auf vielen Websites gibt es die Möglichkeit, dass ein Benutzer seinen Account, in dem u. a. die Adressinformationen gespeichert werden, online pflegen kann. Dem Benutzer soll es möglich sein, einen Account anzulegen, zu bearbeiten und gegebenenfalls wieder zu entfernen. Der Benutzer soll jedoch keinen Zugriff auf die anderen Accounts haben. Das heißt, er soll immer nur Zugriff auf einen Account haben. Dieser Sachverhalt soll sich auch in der URL widerspiegeln.

Aufruf

Mit der folgenden URL könnte ein Benutzer auf seinen Account zugreifen:

http://localhost:3000/account

Wichtig ist hier, dass account im Singular angegeben wird. Es kann weder auf alle noch auf einen bestimmten Account mit einer angegebenen ID zugegriffen werden. Bei einer Singleton-Ressource wird die Ressource nur im Singular angegeben.

Im Folgenden wird gezeigt, wie eine Singleton-Ressource angelegt wird.

  1. Model anlegen

    Für die Speicherung der Account-Daten benötigen wir ein Model und ein Migration-Skript zum Anlegen einer Datenbanktabelle:

    ruby script/generate model account firstname:string \
    lastname:string email:string ...
  2. Erstellen eines Controllers

    Zur Realisierung kann ein Controller mit dem controller -Generator angelegt werden. Wichtig ist, dass der Name des Controllers im Singular angegeben wird. Als weitere Optionen übergeben wir die Actions, die generiert werden sollen.

    ruby script/generate controller account show new edit \
    create update destroy

    Die Actions sind leer und müssen daher selbst ausprogrammiert werden. Damit das System weiß, welchen Account es laden soll, muss ein Authentifizierungssystem implementiert werden.

    Der scaffold - oder resource -Generator ist leider nicht so geeignet, da dieser nur Plural-Ressourcen anlegt.

  3. Routing-Eintrag

    In der Routing-Datei config/routes.rb legen wir folgenden Eintrag an. Achten Sie darauf, dass auch hier die Singular-Schreibweise verwendet wird:

    map.resource :account

Aufgrund dieses Routing-Eintrages sind folgende Zugriffe auf die Ressource account möglich:

  • GET /account
    Es wird der Account-Controller mit der Action show aufgerufen. Diese Action zeigt die Details eines Benutzers. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Account-Details', account_path
  • GET /account/new
    Es wird der Account-Controller mit der Action new aufgerufen. Diese Action lädt das Formular zum Anlegen eines neuen Accounts. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'neuer Account', new_account_path
  • GET /account/edit
    Es wird der Account-Controller mit der Action edit aufgerufen. Diese Action lädt das Formular zum Bearbeiten eines Accounts. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Account bearbeiten', edit_account_path
  • POST /account
    Es wird der Account-Controller mit der Action create aufgerufen. Diese Action erstellt einen neuen Account-Datensatz. Der Aufruf erfolgt über ein Formular:
    form_for(@account) do ... end.
    Die HTTP-Methode muss nicht angegeben werden, da sie automatisch erkannt wird. Wenn das Objekt @account neu ist, wird die POST-Methode verwendet.
  • PUT /account
    Es wird der Account-Controller mit der Action update aufgerufen. Diese Action ändert die Daten des Account-Datensatzes. Der Aufruf erfolgt über ein Formular:
    form_for(@account) do ... end
    Die HTTP-Methode muss nicht angegeben werden, da sie automatisch erkannt wird. Wenn das Objekt @account bereits in der Datenbank vorliegt, wird automatisch die PUT-Methode ausgeführt.
  • DELETE /account
    Es wird der Account-Controller mit der Action destroy aufgerufen. Diese Action löscht den Account. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to "löschen", account_path, :method => :delete

Admin-Controller

Für Administratoren würde es sich anbieten, einen weiteren Controller anzulegen, der für die Verwaltung aller Accounts zuständig ist (siehe Abschnitt kap_resful_namespace). Folgendes Routing würde sich dann anbieten:

Listing  config/routes.rb

map.resource :account

map.namespace(:admin) do |admin|
  admin.resources :account
end

Rheinwerk Computing - Zum Seitenanfang

Ressourcen erweitern  topZur vorigen Überschrift

Mehr Actions erforderlich

Wenn wir den scaffold -Generator einsetzen, stehen uns sieben Actions im Controller zur Verfügung, um eine Ressource zu verarbeiten. Dies reicht gelegentlich jedoch nicht aus.

Beispiel

Angenommen, wir haben eine Bookmark-Ressource. Neben der Verwaltung (Anzeigen, Ändern, Löschen usw.) soll es möglich sein, Bookmarks als wichtig zu markieren oder die Markierung zu entfernen. Außerdem soll es möglich sein, alle markierten Bookmarks aufzulisten.

Dazu sind drei Schritte erforderlich:

  1. Model um Attribut »flag« ergänzen

    Falls Sie bereits eine Tabelle bookmarks haben, diese jedoch noch nicht das Feld flag aufweist, können Sie es mit folgender Migration hinzufügen:

    ruby script/generate migration AddFlagToBookmarks \
    flag:boolean
    rake db:migrate
  2. Controller um die fehlenden Actions ergänzen

    Fügen Sie im BookmarksController die folgenden Actions hinzu:

    class BookmarksController << ApplicationController
      ...
    
      def flag
        @bookmark = Bookmark.find(params[:id])
        @bookmark.update_attribute(:flag, true)
        render :show
      end
    
      def unflag
        @bookmark = Bookmark.find(params[:id])
        @bookmark.update_attribute(:flag, false)
        render :show
      end
    
      def flagged
        @bookmarks = Bookmark.find(:all,
    		 :conditions => {:flag=>true})
        render :index
      end
    end
  3. Routing-Eintrag

    Damit die entsprechenden Actions über die URL aufgerufen werden können, muss noch folgender Routing-Eintrag vorgenommen werden:

    map.resources :bookmarks,
      :member => {
        :flag => :put,
        :unflag => :put
      },
      :collection => {:flagged => :get }

    Da die Actions flag und unflag sich auf ein konkretes Element beziehen, werden sie innerhalb der Option :member definiert. Außerdem wird die HTTP-Methode angegeben.

    Da sich die Action flagged nicht auf ein bestimmtes Element bezieht, wird sie innerhalb der Option :collection definiert. Auch hier wird die HTTP-Methode angegeben.

Aufruf

Aufgrund dieses Routing-Eintrages kann die erweiterte Ressource wie folgt aufgerufen werden:

  • PUT http://localhost:3000/bookmarks/2/flag
    Es wird die Action flag aus dem Bookmarks-Controller aufgerufen. Diese Action setzt das Attribut flag mit der ID 2 auf den Wert true . Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Markieren', flag_bookmark_path(2),
    :method=>:put
  • PUT http://localhost:3000/bookmarks/2/unflag
    Es wird die Action unflag aus dem Bookmarks-Controller aufgerufen. Diese Action setzt das Attribut flag des Bookmarks mit der ID 2 auf den Wert false . Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Markierung aufheben', unflag_bookmark_path(2),
    :method=>:put
  • GET http://localhost:30000/bookmarks/flagged
    Es wird die Action flagged aus dem Bookmarks-Controller aufgerufen. Diese Action listet alle Bookmarks, deren Attribut flag auf true gesetzt ist. Der Aufruf kann mit folgendem View-Helper erfolgen:
    link_to 'Alle markierten Bookmarks listen',
    flagged_bookmarks_path
Routing-Regeln anzeigen
Rails bietet einen sehr praktischen Rake-Task an, der alle Routing-Regeln ausgibt:

rake routes

airports GET /airports {:controller=>"... }
airport GET /airports/:id {:controller=>"... }
new_airport GET /airports/new {:controller=>"... }
edit_airport GET /airports/:id/edit {:controller=>"... }
...



Ihre Meinung

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.

 <<   zurück
  Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Ruby on Rails 2
Ruby on Rails 2
Jetzt Buch bestellen
 Ihre Meinung?
Wie hat Ihnen das Openbook gefallen?
Ihre Meinung

 Buchtipps
Zum Rheinwerk-Shop: Ruby on Rails 3.1






 Ruby on Rails 3.1


Zum Rheinwerk-Shop: Responsive Webdesign






 Responsive Webdesign


Zum Rheinwerk-Shop: Suchmaschinen-Optimierung






 Suchmaschinen-
 Optimierung


Zum Rheinwerk-Shop: JavaScript






 JavaScript


Zum Rheinwerk-Shop: Schrödinger lernt HTML5, CSS3 und JavaScript






 Schrödinger lernt
 HTML5, CSS3
 und JavaScript


 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und der Schweiz
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2008
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.
Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


Nutzungsbestimmungen | Datenschutz | Impressum

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de

Cookie-Einstellungen ändern