Jetzt starten wir den Rails-Webserver:
MacBook:history xyz$ rails server
=> Booting WEBrick
=> Rails 3.2.3 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2012-05-08 19:26:14] INFO WEBrick 1.3.1
[2012-05-08 19:26:14] INFO ruby 1.9.3 (2012-04-20) [x86_64-darwin11.3.0]
[2012-05-08 19:26:14] INFO WEBrick::HTTPServer#start: pid=43118 port=3000
Und wenn Sie auf der Index-Seite auf „Destroy“ klicken, können Sie
nach einer Bestätigungsabfrage einen Datensatz löschen. Ist das cool?! Sie
haben innerhalb von nicht mal 10 Minuten eine Web-Applikation geschrieben,
mit der Sie Datensätze anlegen (
create),
auflisten und anschauen (
read/
retrieve), bearbeiten (
update) und löschen (
delete/
destroy)
können (CRUD)
. Das ist der Zauber von Scaffolding.
Sie werden es sich schon denken können, aber schauen wir uns
trotzdem das Verzeichnis
app/views/chancellors
an:
MacBook:history xyz$ ls app/views/chancellors
_form.html.erb
edit.html.erb
index.html.erb
new.html.erb
show.html.erb
MacBook:history xyz$
Für
index
,
edit
,
new
und
show
liegen
dort die entsprechenden Views. Da
new
und
edit
beide ein Formular zum Bearbeiten der
Daten benötigen, wird dieses im Sinne von DRY (
Don't
Repeat
Yourself) im Partial
_form.html.erb
abgelegt (siehe
„Partials“) und in
new.html.erb
und
edit.html.erb
mit einem
<%= render 'form'
%>
eingebunden.
Öffnen wir einmal die Datei
app/views/chancellors/index.html.erb
:
<h1>Listing chancellors</h1>
<table>
<tr>
<th>First name</th>
<th>Last name</th>
<th>Birthday</th>
<th>Day of death</th>
<th>Inauguration</th>
<th></th>
<th></th>
<th></th>
</tr>
<% @chancellors.each do |chancellor| %>
<tr>
<td><%= chancellor.first_name %></td>
<td><%= chancellor.last_name %></td>
<td><%= chancellor.birthday %></td>
<td><%= chancellor.day_of_death %></td>
<td><%= chancellor.inauguration %></td>
<td><%= link_to 'Show', chancellor %></td>
<td><%= link_to 'Edit', edit_chancellor_path(chancellor) %></td>
<td><%= link_to 'Destroy', chancellor, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
<br />
<%= link_to 'New Chancellor', new_chancellor_path %>
Als mittlerweiler alter ERB-Hase werden Sie keine Probleme haben,
den Code zu lesen und zu verstehen. Falls doch, empfehle ich noch mal
einen schnellen Blick in
„Programmieren in einer erb-Datei“.
In den vom Scaffold Generator generierten Views sind Sie zum
ersten Mal auf den Helper
link_to
gestoßen. Damit werden
<a href ...>
Verlinkungen erzeugt. Man kann natürlich
auch einen Link von Hand mit
<a href="...">
im erb
eintragen, aber für Verlinkungen innerhalb eines Rails-Projektes ist
link_to
praktischer, weil man die Namen der Routen als Ziel
benutzen kann. Der Code wird damit deutlich lesbarer. In obigen Beispiel
gibt es folgende Routen:
MacBook:history xyz$ rake routes
chancellors GET /chancellors(.:format) chancellors#index
POST /chancellors(.:format) chancellors#create
new_chancellor GET /chancellors/new(.:format) chancellors#new
edit_chancellor GET /chancellors/:id/edit(.:format) chancellors#edit
chancellor GET /chancellors/:id(.:format) chancellors#show
PUT /chancellors/:id(.:format) chancellors#update
DELETE /chancellors/:id(.:format) chancellors#destroy
MacBook:history xyz$
Der erste Teil dieser Route ist der Name der Route. Bei einem new
Aufruf ist das
new_chancellor
. Ein Link auf
new_chancellor
sieht im erb-Code so aus (das können Sie am
Ende der Datei
app/views/chancellors/index.html.erb
einsehen):
<%= link_to 'New Chancellor', new_chancellor_path %>
Mit
link_to
können Sie auch auf Resourcen innerhalb
einer RESTful Resource verlinken. Auch dafür finden Sie in
app/views/chancellors/index.html.erb
Beispiele. In
der Tabelle wird zu jedem
chancellor
ein
show
, ein
edit
und ein
destroy
link gerendert:
<% @chancellors.each do |chancellor| %>
<tr>
<td><%= chancellor.first_name %></td>
<td><%= chancellor.last_name %></td>
<td><%= chancellor.birthday %></td>
<td><%= chancellor.day_of_death %></td>
<td><%= chancellor.inauguration %></td>
<td><%= link_to 'Show', chancellor %></td>
<td><%= link_to 'Edit', edit_chancellor_path(chancellor) %></td>
<td><%= link_to 'Destroy', chancellor, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
Rails bestimmt anhand der Resource und der gewählten Route
automatisch die benötigte URL und das benötigte HTTP-Verb (sprich, ob es
sich um ein POST, GET, PUT oder DELETE) handelt. Beim Index- und
Show-Aufruf müssen Sie auf den Unterschied zwischen Plural und Singular
achten. link_to 'Show', chancellor
verlinkt auf einen
einzelnen Datensatz und link_to 'Show', chancellors_path
verlinkt auf die Index-Ansicht.
Ob der Name der Route mit oder ohne den Zusatz _path
in link_to
verwendet wird, hängt davon ab, ob Rails sich
anhand der restlichen Informationen die Route "denken" kann. Wird nur
ein Objekt (in unserem Beispiel die Variable
chancellor
) angegeben, dann geht Rails automatisch
davon aus, dass es sich um eine show-Route handelt.
Beispiele:
Zugriff per XML oder JSON
Rails' Scaffolding generiert per Default nicht nur den Zugriff per
HTML für „menschliche“ Benutzer, sondern auch direkt noch eine
Schnittstelle für Automaten. Damit lassen sich die gleichen Methoden
index
, show
,
new
, create
,
update
und destroy
aufrufen. Eben nur in einem für eine Maschine einfacheren Format.
Beispielhaft besprechen wir hier die
index
-Action, mit der alle Daten auf einmal
ausgelesen werden. Über die gleiche Idee können aber auch Daten gelöscht
(destroy
) oder geändert
(update
) werden.
Wenn Sie keinen maschinellen Zugriff auf Daten benötigen, können
Sie diese Beispiele überspringen. Sie sollten dann aber auch
sicherheitshalber alle Zeilen mit format.xml
bzw.
format.json
in den respond_to
-Blöcken in Ihren
Controllern löschen. Ansonsten haben Sie eine Schnittstelle zu den
Daten, die Sie vielleicht irgendwann mal vergessen und die eine
potenzielle Sicherheitslücke darstellen.
Ganz am Anfang von
app/controllers/chancellors_controller.rb
finden
Sie den Eintrag für die
index
-Action:
class ChancellorsController < ApplicationController
# GET /chancellors
# GET /chancellors.json
def index
@chancellors = Chancellor.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @chancellors }
end
end
[...]
Der Code ist übersichtlich. In der Instanz-Variable
@chancellors
werden alle Bundeskanzler
abgespeichert. Danach wird irgendetwas mit einem Format gemacht. Hmmm
… da steht was von
json
. Probieren wir mal Folgendes aus:
Bitte starten Sie mit
rails server wieder den
Rails-Server und gehen Sie mit Ihrem Webbrowser auf die URL
http://0.0.0.0:3000/chancellors.json
.
Heureka! Sie bekommen folgende Ansicht:
Die URL
http://0.0.0.0:3000/chancellors.json
gibt uns alle Kanzler im JSON-Format aus. In Rails 3.0 war hier der
Default noch XML. Ob XML oder JSON ist aber eigentlich auch egal. Die
coolen JavaScript-Programmierer haben halt lieber JSON und da ja heute
an jeder Ecke ein AJAX-Element eingebaut wird, lag der Schritt nahe,
den Default von XML auf JSON zu ändern.
Wenn Sie keine JSON-Ausgabe wünschen, müssen Sie diese Zeile in
der app/controllers/chancellors_controller.rb
löschen.
Wenn Sie in einer Rails-Applikation einmal eine JSON- und eine
XML-Schnittstelle benötigen, so müssen Sie im Controller einfach nur
beide Varianten im
respond_to
-Block angeben. Hier ein
Beispiel mit der
app/controllers/chancellors_controller.rb
in der
index
-Action:
class ChancellorsController < ApplicationController
# GET /chancellors
# GET /chancellors.json
def index
@chancellors = Chancellor.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @chancellors }
format.xml { render xml: @chancellors }
end
end
[...]