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 bestellen
* versandkostenfrei in (D) und (A)
Pfeil 5 Eine einfache Bookmarkverwaltung
  Pfeil 5.1 Rails-Projekt erstellen
  Pfeil 5.2 Weitere Views anlegen
  Pfeil 5.3 Layout
  Pfeil 5.4 Model
  Pfeil 5.5 CRUD - Create - Read - Update - Delete
  Pfeil 5.6 Fehlerbehandlung in Formularen
  Pfeil 5.7 Flash-Messages
  Pfeil 5.8 Refaktorisierung mit Helper und Partials
  Pfeil 5.9 Authentifizierung
  Pfeil 5.10 Routing
  Pfeil 5.11 RESTful Rails
  Pfeil 5.12 Darstellungsformate in RESTful Rails
  Pfeil 5.13 Ajax


Rheinwerk Computing - Zum Seitenanfang

5.8 Refaktorisierung mit Helper und Partials  Zur nächsten ÜberschriftZur vorigen Überschrift

In diesem Abschnitt werden wir an der Funktionalität unserer Beispiel-Applikation nichts ändern, sondern wir werden unseren Programm-Quelltext vereinfachen und dadurch u. a. die Wartbarkeit, Erweiterbarkeit und Lesbarkeit des Quelltexts verbessern. Dies wird in der Software-Entwicklung als Refaktorisierung bezeichnet.


Rheinwerk Computing - Zum Seitenanfang

Helper  Zur nächsten ÜberschriftZur vorigen Überschrift

Wenn wir einen neuen Bookmark anlegen möchten, einen vorhandenen ändern möchten oder uns die Details zu einem Bookmark ansehen, haben wir immer die Möglichkeit, über einen Link »Zurück zur Liste« zurück zur Index-Seite zu gehen. Das haben wir umgesetzt, indem wir den Link in den drei Views new.html.erb, edit.html.erb und show.html.erb angelegt haben. Das widerspricht zum einen dem Rails zugrunde liegenden DRY-Prinzip (»Don't repeat yourself«) und ist zum anderen schwer zu warten. Denn sollte sich an diesem Link etwas ändern, müssen wir das an diesen drei Stellen ändern.

Helper selbst programmieren

Bei der Erstellung des Formulars haben wir zum Beispiel einige von Rails zur Verfügung gestellte Helper benutzt, die automatisch für uns HTML-Code generiert haben. Das Konzept der Helper möchten wir auch gerne nutzen, um unsere Zurück-Links zu generieren. Leider stellt uns Rails dazu keinen Helper zur Verfügung. Das macht aber weiter nichts, da wir selbst einen Helper programmieren können. Und das ist einfacher, als sich das jetzt anhört.

app/helpers

Beim Anlegen unserer Bookmark-Applikation (rails bookmarks) wurde automatisch das Verzeichnis app/helpers erstellt, und bei der Generierung des Controllers bookmarks (ruby script/generate controller bookmarks) wurde in diesem Verzeichnis passend zum Controller die Datei bookmarks_helper.rb angelegt:

Listing  app/helpers/bookmarks_helper.rb

module BookmarksHelper
end

Und diese Helper-Datei können wir nutzen, um in Ruby-Code eine Methode zu erstellen, die zum Beispiel den Zurück-Link generiert. Die Methode nennen wir back_to_list, und in diese Methode setzen wir die Generierung eines Links über den vorhandenen ActionView-Helper von Rails:

Listing  app/helpers/bookmarks_helper.rb

module BookmarksHelper

  def back_to_list
    link_to "Zurück zur Liste", :action => "index"
  end

end

In unseren Views new.html.erb, edit.html.erb und show.html.erb ersetzen wir die Zurück-Links durch den Aufruf des Helpers back_to_list:

<p><%= back_to_list %></p>

Wenn Sie einen Test im Browser machen, sollten Sie keine Veränderung im Vergleich zu vorher feststellen.

content_tag

Angenommen, wir wollten einen div -Tag um die Ausgabe dieses Links definieren, um diesen später über CSS formatieren zu können, dann können wir den div -Tag auch in die Helper-Methode auslagern. Da wir dann auch HTML-Code ausgeben müssten, könnten wir das über einen zusammengesetzten String lösen, aber Rails stellt uns dazu den Helper content_tag zur Verfügung:

Listing  app/helpers/bookmarks_helper.rb

module BookmarksHelper
  def back_to_list
    content_tag(:div,
    link_to ("Zurück zur Liste", :action => "index"),
    :class => "subNavigation")
  end
end

Wenn Sie das im Browser testen und sich den HTML-Code der Seite ansehen, sehen Sie, dass um den Zurück-Link ein div -Tag gesetzt wurde mit der Klasse subNavigation:

<p>
  <div class="subNavigation">
    <a href="/bookmarks">Zurück zur Liste</a>
  </div>
</p>

Wenn wir uns unsere Dateien näher ansehen, fällt uns auf, dass wir zum Beispiel in der show.html.erb die beiden Datumswerte Erstellungs- und Änderungsdatum in ein deutsches Datumsformat umwandeln. Dazu nutzen wir zweimal die Methode strftime . Auch das können wir vereinfachen, indem wir einen eigenen Helper zur Datumsumwandlung entwickeln. Unsere Methode soll german_time heißen und erhält das Datum im datetime -Format als Parameter. Dazu ändern wir die show.html.erb wie folgt:

Listing  app/views/bookmarks/show.html.erb

<p>Erstellt am: <%= german_time(@bookmark.created_at) %></p>

<p>Geändert am: <%= german_time(@bookmark.updated_at) %></p>

Die Methode german_time definieren wir in der Helper-Datei bookmarks_helper.rb:

def german_time(time)
  time.strftime("%d.%m.%Y %H:%M")
end

Auch dieses Mal sollten Sie beim Test im Browser keine Veränderung im Vergleich zu vorher feststellen.

application_helper.rb

Da man diese Datumsformatierung vielleicht öfter gebrauchen kann, also auch in anderen Controllern der Applikation, ist es sinnvoll, die Helper-Methode nicht in der Datei app/helpers/bookmarks_helper.rb zu speichern, sondern in app/helpers/application_helper.rb:

Listing  app/helpers/application_helper.rb

# Methods added to this helper will be available to all
# templates in the application.
module ApplicationHelper

  def german_time(time)
    time.strftime("%d.%m.%Y %H:%M")
  end

end
Helper-Methoden nutzen
Seit Rails 2.0 werden automatisch alle Helper-Dateien aus dem Verzeichnis app/helpers geladen. Es spielt daher im Prinzip keine Rolle, in welcher Helper-Datei Sie die Helper-Methoden definieren. Es ist jedoch üblich, Helper-Methoden, die nur für einen bestimmten Controller, z. B. für den Bookmarks-Controller, bestimmt sind, in der Datei bookmarks_helper.rb abzulegen. Helper, die controllerübergreifend verwendet werden können, werden oft in der Helper-Datei application_helper.rb definiert. Man könnte auch eine Helper-Datei nur für Formatierungshelper, wie z. B. formattings_helpers.rb , erstellen.

Die Refaktorisierungen, die wir bis jetzt durchgeführt haben und die wir noch durchführen werden, dienen nicht nur dazu, den Code kürzer und schöner zu machen. Sie haben vor allem den Sinn, dass, wenn wir etwas ändern, was wir an mehreren Stellen benutzt haben, wir das nur an einer Stelle ändern müssen, und schon wirkt sich diese Änderung an allen anderen Stellen aus.


Rheinwerk Computing - Zum Seitenanfang

Partials  topZur vorigen Überschrift

An einer Stelle haben wir das nämlich nicht beachtet und deshalb einen kleinen Fehler in unserer Applikation. Wir haben bei der Erstellung des Ändern-Formulars (edit.html.erb) der Einfachheit halber das Formular zum Erstellen eines Bookmarks (new.html.erb) kopiert. Später haben wir dann wegen der Usability unseres Formulars in der new.html.erb Fehlermeldungen hinzugefügt, die ausgegeben werden, wenn der Benutzer nicht alle Pflichtfelder ausfüllt. Und was passiert, wenn der Benutzer ein leeres Ändern-Formular abschickt? Die Bereiche werden rot markiert, aber der Fehlertext wird nicht angezeigt!

Das heißt, wir müssen auch hier refaktorisieren. Aber wie machen wir das? Das Formular enthält viel zu viel HTML-Code, als dass wir diesen über content_tag, so wie eben bei der Formatierung des Zurück-Links, in einer eigenen Helper-Methode ausgeben könnten.

Für die Lösung dieses Problems kennt Rails sogenannte Partials - eigene Dateien, in die wir HTML-Code auslagern können. Die Partials liegen im gleichen Verzeichnis wie die Views, die die Partials einbinden, und ihr Name beginnt immer mit einem Unterstrich.

Partials einbinden

Das heißt, wir lagern das Formular aus dem View new.html.erb in die Datei _form.html.erb, die wir im Verzeichnis app/views/bookmarks anlegen, aus. Das Einbinden eines Partials erfolgt über den Befehl:

render :partial => "Name des Partials ohne führenden Unterstrich und ohne Dateiendung"

Diesen Befehl setzen wir in unsere new.html.erb ein:

Listing  app/views/bookmarks/new.html.erb

<% @title = "neu" %>
<h2>Neuen Favorit erstellen</h2>
<%= render :partial => "form" %>
<p><%= back_to_list %></p>

:locals

Für die new.html.erb funktioniert das ohne Probleme. Obwohl die Formulare in der new.html.erb und edit.html.erb identisch sind, können wir das Partial _form.html.erb nicht in die edit.html.erb übernehmen, weil das Ändern-Formular an eine andere URL geschickt wird als das Anlageformular. Das müssen wir im Partial berücksichtigen. Wir müssen den Wert für die URL, an die das Formular geschickt wird, dem Formular als Variable übergeben, die wir beim Aufruf des Formulars, also beim Rendern, setzen. Das bedeutet, wir müssen sowohl in der _form.html.erb als auch in der new.html.erb und der edit.html.erb etwas ändern:

Im Partial _form.html.erb definieren wir die lokale Variable url:

<% form_for :bookmark, :url => url do |f| %>

In der new.html.erb und der edit.html.erb übergeben wir die URL als lokale Variable url:

Listing  app/views/bookmarks/new.html.erb

<%= render :partial => "form",
:locals => {:url => {:action => "create"}} %>

Listing  app/views/bookmarks/edit.html.erb

<%= render :partial => "form",
:locals => {:url => {:action => "update",
:id => @bookmark.id}} %>

submit_tag

Man könnte jetzt auch noch so weit gehen und die Buttons zum Absenden des Formulars unterschiedlich benennen. Dazu müssen wir in der _form.html.erb auch dafür eine Variable definieren (submit_text):

<%= submit_tag submit_text %>

Und diese Variable setzen wir dann sowohl in der new.html.erb:

<%= render :partial => "form",
:locals => {:url => {:action => "create"},
:submit_text => "Neuen Favorit erstellen"} %>

als auch in der edit.html.erb:

<%= render :partial => "form",
:locals => {:url => {:action => "update",
:id => @bookmark.id}, :submit_text => "ändern"} %>

Partials unterscheiden sich von Helpern dadurch, dass Helper richtige Methoden sind, während in Partials HTML-Code ausgelagert wird, ihnen aber auch ähnlich wie bei Methoden Parameter übergeben werden können.

Ausgabe von Arrays

Auch die Ausgabe von Arrays kann in ein Partial ausgelagert werden. Wir geben zum Beispiel auf unserer Index-Seite index.html.erb alle Bookmarks in einer Liste aus. Wenn wir das an mehreren Stellen tun würden, könnten wir den Bereich mit den einzelnen Listeneinträgen in ein Partial (_bookmark.html.erb) auslagern und beim Aufruf des Partials in der index.html.erb die Instanzvariable @bookmarks übergeben. Ab Rails 2.0 wird dann das Partial für jedes Element des Arrays aufgerufen:

Listing  app/views/bookmarks/_bookmark.html.erb

<li>
  <%= link_to h(bookmark.title), h(bookmark.url) %>
  (<%= link_to "Details", :action => "show",
  :id => bookmark.id %> |
  <%= link_to "ändern", :action => "edit",
  :id => bookmark.id %> |
  <%= link_to "löschen", {:action => "destroy",
  :id => bookmark.id},
  :confirm => "Wollen Sie diesen Datensatz wirklich
	      löschen?" %>
  )
</li>

Listing  app/views/bookmarks/index.html.erb

...
<ul>
  <%= render :partial => @bookmarks %>
</ul>
...

An den hier gezeigten Refaktorisierungsbeispielen sieht man, dass man immer versuchen sollte, zunächst lauffähigen Code zu erstellen, diesen dann aber so schnell wie möglich refaktorisieren sollte. Das bedeutet, dass der Code schöner und schlanker wird und besser zu warten, ohne dass sich nach außen etwas ändert. Später werden wir noch Testverfahren kennenlernen, die dafür sorgen, dass es bei einer Refaktorisierung nicht zu einer Veränderung der Funktionalität kommt.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
 <<   zurück
  Zum Katalog
Zum Katalog: Ruby on Rails 2
Ruby on Rails 2
Jetzt bestellen
 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: Ruby on Rails 3.1






 Ruby on Rails 3.1


Zum Katalog: Responsive Webdesign






 Responsive Webdesign


Zum Katalog: Suchmaschinen-Optimierung






 Suchmaschinen-
 Optimierung


Zum Katalog: JavaScript






 JavaScript


Zum Katalog: Schrödinger lernt HTML5, CSS3 und JavaScript






 Schrödinger lernt
 HTML5, CSS3
 und JavaScript


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
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.


[Rheinwerk Computing]

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