Donnerstag, 24. Mai 2012


Artikel

August 2006 | Artikel

Einführung und Überblick in die Webentwicklung mit Ruby on Rails Fortsetzung, Teil 2

Teil 1   Teil 2   Teil 3   

Controller und Views
Für die Entwicklung von Controllern und Views stellt Ruby on Rails die Frameworks Action Controller und Action View zur Verfügung. Das Mapping eines Requests auf einen Controller erfolgt dabei ohne Konfiguration anhand der URL. Per Default besteht die URL neben der Domain, aus dem Namen des Controllers und der Action, die den Request entgegennimmt. Optional folgen weitere Parametern wie z.B. die ID des zu bearbeitenden Datensatzes (Abb. 1). Dadurch entfällt jegliche Konfiguration.

Die Verarbeitung eines Requests erfolgt durch eine Action, d.h. eine öffentliche Methode auf einer Controller-Klasse. Listing 4 zeigt z.B. die Definition des BookController mit den Actions (Methoden) list und update.
Typischerweise werden durch Actions die Modelle erzeugt, gelesen, aktualisiert oder gelöscht. Als Ergebnis liefert die Action einen View oder führt eine Weiterleitung auf eine andere Action aus. Dabei wird von einer Action per Konvention und ohne Konfiguration ein View ausgeliefert, der den gleichen Namen wie die Action hat. So liefert z.B. die Action list in Listing 4 den View list.rhtml aus. Ein Controller greift auf einfache Weise auf Request- und Session-Parameter zu, die jeweils in einer Hash abgelegt sind. Über Filter können Requests vor der Verarbeitung gefiltert werden. So wird z.B. über den Filter authenticate in Listing 4 vor jeder Action geprüft, ob der Anwender angemeldet ist. Auch hier ist keine Konfiguration erforderlich.

  1. Listing 4
  2. ------------------------------------------------------------
  3. class BookController < ApplicationController
  4. before_filter :authenticate
  5. def list
  6. @books = Book.find(:all)
  7. end
  8. def update
  9. book = Book.find(params[:id])
  10. book.attributes = params[:book]
  11. book.save
  12. redirect_to :action => ”list”
  13. end
  14. end

Das Framework Action View ist für die Repräsentation der Daten zuständig. Views werden dabei über Template-Dateien definiert, die neben HTML auch eingebetteten Ruby-Code enthalten. Der Code in Listing 5 definiert z.B. die Anzeige einer Liste von Büchern. Komplexere Logik wird dabei in so genannte Helper-Module ausgelagert, von denen Rails bereits jede Menge zur Verfügung stellt. Über Partial Views können Teile von Seiten ausgelagert und in anderen Seiten wieder verwendet werden (DRY-Prinzip). Durch die Verwendung von Layouts werden die Grundstruktur und das Aussehen der Seiten in einem zentralen View pro Anwendung, Controller oder Action definiert. Das Blättern durch lange Liste wird ebenfalls von Haus aus unterstützt.

  1. Listing 5
  2. -------------------------------------------------------------
  3. # app/views/book/list.rhtml
  4. <table>
  5. <% @books.each do |book| %>
  6. <tr><td><%= book.title</td>…</tr>
  7. <% end %>
  8. </table>
Anwendungsrahmen und Scaffolding
Ein Projekt startet immer mit der Erzeugung des Anwendungsrahmens über den Befehl rails <Projektname>. Dadurch erzeugt Rails eine Verzeichnisstruktur, die für jedes Projekt identisch ist.
Durch diese weitere Konvention ist immer und sofort klar, wo welche Dateien (Modelle, Controller, Views, Tests, usw.) abgelegt werden bzw. zu finden sind. Die Einarbeitung in bestehende Projekte wird hierdurch außerdem erleichtert. Modelle und Controller werden initial über Generatoren erzeugt, die neben der Klasse selber auch entsprechende Unit Tests, Fixtures, Helper-Module etc. erzeugen. Statt die Controller und Views von Hand zu implementieren, kann eine einfache und sofort lauffähige Version über das so genannte Scaffolding auf zwei Arten erreicht werden. Bei der ersten Möglichkeit erzeugt Rails durch die Definitionszeile aus Listing 6 alle notwendigen Actions zur Anzeige und Bearbeitung des Modells zur Laufzeit.

  1. Listing 6
  2. ----------------------------------------------
  3. # RAILS_ROOT/app/controllers/book_controller.rb
  4. class BookController < ApplicationController
  5. scaffold :book
  6. # Actions new, edit, update, list, …
  7. # stehen ohne expliziten Code bereit
  8. end

Bei der zweiten Möglichkeit erzeugt Rails den entsprechenden Quellcode, der als Vorlage für die weitere Arbeit dienen kann. In beiden Fällen kann die Anwendung anschließend sukzessiv um individuelle Funktionalität und Views erweitert werden und bleibt dabei zu jedem Zeitpunkt lauffähig.

Datenbankmigration
Datenbankerweiterung wird in Rails nicht (mehr) in SQL programmiert, sondern in Ruby. Dazu bietet Rails so genannte Migrationsskripte mithilfe derer von einer Schemaversion auf eine andere (vor und zurück) mit einem Befehl migriert werden kann. Listing 7 zeigt ein Migrationsskript für die Erzeugung der Tabelle books.

  1. Listing 7
  2. --------------------------------------------------------------
  3. # RAILS_ROOT/db/migrate/001_initial.rb
  4. class CreateBooks < ActiveRecord::Migration
  5. def self.up
  6. # erzeuge Tabelle books
  7. create_table :books do |t|
  8. t.column :title, :string
  9. t.column :author, :string
  10. t.column :publisher, :string
  11. end
  12. # Initiale Daten aus CSV-Datei einfügen usw.
  13. end
  14. def self.down
  15. # löschen Tabelle wieder
  16. drop_table :books
  17. end
  18. end

Migrationsskripte haben den Vorteil, dass die Schemata inklusive Daten in Ruby und damit datenbankunabhängig vorliegen. Der Wechsel einer Datenbank wird somit erleichtert. Ebenso werden die Teamarbeit an unterschiedlichen Versionsständen und die Verwaltung der Migrationen im Repository ermöglicht. Da es sich um Ruby-Programme handelt, können hier jegliche Aktionen durchgeführt werden. Die Projektautomatisierung wird hierdurch deutlich erleichtert.

E-Mail und Web Services
Über das Framework Action Mailer bietet Rails eine gute Unterstützung für den Versand von E-Mails. E-Mail-Texte werden dabei mithilfe von Templates (analog den Views) erzeugt und können dadurch auch dynamische Anteile enthalten. Der Versand erfolgt über SMTP oder per Sendmail.
Mithilfe des Frameworks Action Web Services ermöglicht Rails das Exportieren von Actions als Web Services oder den Aufruf von Web Services aus der Anwendung. Als Protokolle stehen SOAP oder XML-RPC bereit. Die Testbarkeit der Funktionalität ist durch Rails von vornherein berücksichtigt.

AJAX
Rails ist eines der ersten Web-Frameworks mit umfangreicher AJAX-Unterstützung (Asynchronous JavaScript and XML). AJAX ermöglicht die Entwicklung reicher und hoch interaktiver Webanwendungen und ist eine der Basistechnologien für Web 2.0. Die Anwendung verhält sich sehr viel flüssiger als von klassischen Webanwendungen gewöhnt. Rails liefert dazu die Prototype-Bibliothek mit aus und stellt Wrapper für den einfachen Zugriff auf deren Funktionen zur Verfügung. Seit Rails 1.1 können über so genannte RJS-Templates per Ruby-Code gleich mehrere DOM-Elemente auf der Seite mit einem Request aktualisiert werden (Listing 8).

  1. Listing 8
  2. -----------------------------------------------------
  3. page.insert_html :bottom, 'list', '<li>Rails</li>’
  4. page.visual_effect :highlight, 'list', :duration => 3
  5. page.replace_html 'header', 'RJS Template Test Complete!'
Testbarkeit
Von Beginn an wurde auf die Testbarkeit von Rails-Anwendungen Wert gelegt. Unit Tests sind in allen MVC-Ebenen leicht möglich. Modelle und Controller werden ohne laufenden Server durch einfache Aufrufe der entsprechenden Methoden getestet. Selbst Views können bis hin zu beliebig tief verschachtelten HTML-Tags geprüft werden. Rails 1.1 bietet Integration Tests, mithilfe derer zum Beispiel der Weg eines Benutzers durch die Anwendung, d.h. über mehrere Controller hinweg, getestet werden kann (Listing 9). Dabei kommt die Ausdruckstärke von Ruby wieder zum Tragen und unterstützt die Erstellung einer domainspezifischen (Test-)Sprache. Insgesamt bietet Rails damit eine erstklassige Testunterstützung.

  1. Listing 9
  2. --------------------------------------------------------------
  3. # Integrationstest : test/integration/stories_test.rb
  4. class StoriesTest < ActionController::IntegrationTest
  5. def test_login_person
  6. new_session do |bob|
  7. bob.goes_to_login
  8. bob.login_with :user_login => "bob",
  9. :user_password => "test"
  10. bob.select_project(:myproject)
  11. end
  12. end
  13. private
  14. module MyTesting
  15. def goes_to_login
  16. get "account/login"
  17. assert_response :success
  18. assert_template "account/login"
  19. end
  20. end

Teil 1   Teil 2   Teil 3   

Kommentare