8.6 Partials 

Es kommt immer wieder vor, dass wir den gleichen Ruby- und HTML-Code an mehreren Stellen im Template benötigen. Sei es, um Ergebnisse anzuzeigen, Loginmasken darzustellen oder um Formulare zum Anlegen und Editieren von Datensätzen auszugeben. Da wir in Rails dem DRY-Prinzip (»Don't repeat yourself«) folgen, wollen wir, dass dieser Code zwar mehrfach ausgegeben werden kann, aber nur an einer Stelle definiert wird.
Das können wir erreichen, indem wir sogenannte Partials verwenden. Ein Partial ist ein Subtemplate, das wir innerhalb anderer Template-Dateien laden können und dem wir auch Variablen übergeben können.
Führender Unterstrich
Ein Partial ist eine Template-Datei wie jede andere auch, mit dem einzigen Unterschied, dass sein Dateiname mit einem Unterstrich beginnt.
Abbildung Partials
Die Formulare zum Anlegen (edit.html.erb) und Editieren (new.html.erb) eines Mitarbeiters, in unserer Beispiel-Applikation employees haben wir im Rahmen des letzten Abschnitts unterschiedlich stark weiterentwickelt. Die beiden Formulare sollen aber den gleichen Aufbau haben.
Formulare auslagern
Das heißt, wir können das Formular in ein Partial auslagern, das dann sowohl von dem Template new.html.erb als auch von dem Template edit.html.erb eingebunden wird.
Dazu entfernen wir den Code für das Formular aus der Datei edit.html.erb und fügen ihn in eine neue Datei _form.html.erb im gleichen Verzeichnis ein.
Listing app/views/employees/_form.html.erb
<% form_for(@employee) do |f| %>
<p>
<%= f.label :title, "Anrede" %><br />
<%= f.select :title,
Employee::TITLES,
:include_blank => true,
:prompt => "Bitte wählen"
%>
...
<p>
<%= f.submit "Update" %>
</p>
<% end %>
In den Templates edit.html.erb und new.html.erb laden wir das Partial über den Befehl render :partial =>"form":
Listing app/views/employees/edit.html.erb
<h1>Editing employee</h1>
<%= render :partial => "form" %>
<%= link_to 'Show', @employee %> |
<%= back_to_list %>
Listing app/views/employees/new.html.erb
<h1>New employee</h1>
<%= render :partial => "form" %>
<%= back_to_list %>
Schreibweise der Partials beachten |
Beachten Sie, dass der Dateiname des Partials zwar mit einem Unterstrich beginnt, aber die Angabe des Partials im render -Befehl ohne Unterstrich und ohne Angabe der Dateiendung erfolgt. |
Übergabe von Parametern mit :locals 

Sowohl im Template zum Anlegen eines Mitarbeiters als auch im Template zum Editieren eines Mitarbeiters wird das Formular angezeigt. Das Einzige, was noch unschön an dem Formular ist, ist, dass der Button zum Absenden des Formulars immer mit »Update« beschriftet ist.
Parameter :locals
Über den Parameter :locals der render -Methode kann ein Hash an ein Partial übergeben werden, dessen Schlüssel dann als lokale Variablen in dem Partial zur Verfügung stehen. Das heißt, wir können die Beschriftung des Buttons in einem Hash an das Partial übergeben:
Listing app/views/employees/edit.html.erb
<h1>Editing employee</h1>
<%= render :partial => "form",
:locals => {:submit_text => "Ändern"}
%>
<%= link_to 'Show', @employee %> |
<%= back_to_list %>
Listing app/views/employees/new.html.erb
<h1>New employee</h1>
<%= render :partial => "form",
:locals => {:submit_text => "Erstellen"}
%>
<%= back_to_list %>
Innerhalb des Partials _form.html.erb steht der Schlüssel submit_text aus dem Hash als lokale Variable zur Verfügung:
Listing app/views/employees/_form.html.erb
...
<p>
<%= f.submit submit_text %>
</p>
Der Code für das Formular befindet sich also jetzt nur noch in einer Datei, nämlich in dem Partial _form.html.erb, und wird von zwei Templates (new.html.erb und edit.html.erb) benutzt, die jeweils eine lokale Variable für die Beschriftung des Absendebuttons an das Partial übergeben.
Wir könnten beliebig viele weitere Variablen in dem Hash übergeben, die dann als lokale Variablen in dem Partial zur Verfügung ständen.
Partials mit Ressourcen 

Ein Mitarbeiter (employee) stellt eine Ressource dar. In unserer Datenbank haben wir in der Regel mehrere Mitarbeiter bzw. eine Menge von Ressourcen vom Typ Employee.
Ausgabe von Attributen
Die Ausgabe von Attributen zu einer Ressource (in unserem Fall employee) können wir in ein Partial auslagern, das so heißt wie die Ressource. Wir erstellen also ein Partial _employee.html.erb, das wir im Verzeichnis views/employees/ ablegen.
Listing app/views/employees/_employee.html.erb
<div>
<p>
<b>Firstname:</b>
<%=h employee.firstname %>
</p>
<p>
<b>Lastname:</b>
<%=h employee.lastname %>
</p>
<p>
<b>Birthday:</b>
<%=h employee.birthday %>
</p>
<p>
<b>Comment:</b>
<%=h employee.comment %>
</p>
<%= link_to 'Show', employee %>
<%= link_to 'Edit', edit_employee_path(employee) %>
<%= link_to 'Destroy', employee, :confirm => 'Are you sure?',
:method => :delete %>
</div>
Um nun die Ressource Mitarbeiter auszugeben, können wir im Template show.html.erb das Partial einfach wie folgt aufrufen:
Listing app/views/employees/show.html.erb
<h2>Mitarbeiter Details</h2>
<%= render :partial => @employee %>
Keine Schleife erforderlich
In der Datei index.html.erb möchten wir hingegen mehrere Mitarbeiter ausgeben. Dies geht in Rails 2 ganz einfach, indem man einfach das Array der Mitarbeiter (@employees), das im Controller erzeugt wird, übergibt. Rails ruft dann für jeden einzelnen Mitarbeiter, also für jedes Element des Arrays, das Partial auf. Sie müssen also nicht selbst eine Schleife programmieren.
Listing app/views/employees/index.html.erb
<h2>Liste der Mitarbeiter</h2>
<%= render :partial => @employees %>
Trenner
Wenn man zwischen den einzelnen Ausgaben der Mitarbeiter einen Trenner wie zum Beispiel eine horizontale Linie <hr /> ausgeben möchte, kann man den HTML-Code für den Trenner in ein eigenes Partial auslagern (z. B. _space.html.erb) und dieses mit dem Befehl
:spacer_template => "space"
innerhalb des render :partial - Befehls aufrufen. Das Trennertemplate wird dann immer zwischen der Ausgabe der einzelnen Instanzen des Arrays von Ressource-Objekten aufgerufen:
<%= render :partial => @employees,
:spacer_template => "space" %>
Erleichterungen in Rails 2 |
Die Möglichkeit, dem Paramter :partial entweder ein oder mehrere Ressource-
Objekte zu übergeben, wie zuvor beschrieben, ist erst in Rails 2
eingeführt worden. In Rails 1.2 mussteman für render :partial => @employee
umständlich
render :partial=>"employee", :object=>@employee render :partial => "employee", :collection=>@employees |
Shared Partials 

Partials anderer Controller
Innerhalb eines Templates kann man nicht nur auf Partials zugreifen, die zum gleichen Controller gehören, also im gleichen Verzeichnis abgelegt sind wie das aufrufende Template, sondern man kann auch Partials anderer Controller laden, die also in anderen Verzeichnissen innerhalb des Verzeichnisses app/views liegen. In einem solchen Fall übergeben Sie beim Aufruf des Partials statt des Namens des Partials den Pfad zum Partial innerhalb des Verzeichnisses app/views:
Beispielaufruf eines Partials, das zu einem anderen Controller gehörtrender :partial => "departments/form"
Es gibt Elemente, wie zum Beispiel Copyright-Hinweis, die wir an mehreren Stellen der Applikation benötigen, die aber zu keinem bestimmten Controller gehören. Trotzdem kann man auch solche Texte in ein Partial auslagern. Das Partial können Sie in dem Verzeichnis shared ablegen, das Sie vorher innerhalb des Verzeichnisses app/views manuell erstellt haben. Diese Partials werden Shared Partials genannt. Statt shared können Sie das Verzeichnis auch anders nennen. Es ist unter den Rails-Entwicklern jedoch üblich, diesen Namen zu verwenden.
Abbildung Partials
Zugriff auf Shared Partial
Der Zugriff auf ein Shared Partial erfolgt genauso, wie der Zugriff auf ein Partial, das zu einem anderen Controller gehört, indem Sie beim Aufruf den Pfad zum Partial übergeben:
Listing app/views/employees/index.html.erb
<h1>Liste der Mitarbeiter</h1>
...
<%= render :partial => "shared/copyright" %>
Im Partial _copyright.html.erb befindet sich folgender HTML-Code:
Listing app/views/shared/_copyright.html.erb
<p>© 2007 by xyz</p>
Layout-Partials 

In Rails 2 gibt es die Möglichkeit, eigene Layouts für Partials anzulegen. Diese Layout-Dateien werden nicht im Verzeichnis app/views/layouts abgelegt, sondern zu den zugehörigen Partials.
Um eine eigene Layout-Datei für unser Partial _copyright.html.erb anzulegen, erstellen wir im Verzeichnis app/views/shared die Datei _copyright_full.html.erb . An der Stelle, an der der Inhalt des Partials _copyright.html.erb eingefügt werden soll, geben wir yield an:
Listing app/views/shared/_copyright_full.html.erb
<div id="copyright">
<%= yield %>
<p>All Rights reserved</p>
</div>
Damit die Layout-Datei genutzt wird, müssen wir sie im Aufruf des Partials im Template index.html.erb über den Parameter :layout übergeben:
Listing app/views/employees/index.html.erb
<h1>Liste der Miarbeiter</h1>
...
<%= render :partial => "shared/copyright",
:layout => "shared/copyright_full"
%>
Zusammenfassung
Durch den Einsatz von Partials haben wir die Möglichkeit, HTML-Code, den wir an mehreren Stellen benötigen, nur einmal zu definieren. Wir können Partials auch controller-übergreifend verwenden, und wir können sogar HTML-Code in Partials auslagern, der nicht zu einem Controller gehört. Ab Rails 2.0 können wir für die Partials eigene Layouts anlegen.
Es bietet sich an, die Layout-Partials auch für das Employee-Partial einzusetzten. Man könnte zwei Layouts erstellen. Bei dem einen Layout werden nur grundlegende Informationen zu einem Mitarbeiter angezeigt und bei dem anderen alle Details.
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.