5.7. Wann sollte man Scaffolding benutzen?
Die Verwendung von Scaffolding sollte nie Selbstzweck sein. Es gibt
sehr viele Rails-Entwickler, die nie Scaffolding benutzen und immer alles
selber von Hand aufbauen. Ich finde Scaffolds für einen schnellen Einstieg
in ein neues Projekt ganz praktisch. Aber es ist immer nur der
Anfang.
Beispiel für ein Minimal-Projekt
Nehmen wir einmal an, wir bräuchten auf die Schnelle eine
Webseite, mit der man Kanzler auflisten und einzeln darstellen kann.
Aber es würde keine Editier- oder Löschfunktion benötigt werden. In
diesem Fall wäre ein Großteil des mit Scaffold angelegten Codes unnütz
und müsste gelöscht werden. Probieren wir es nachfolgend aus:
MacBook:~ xyz$ rails new history2
[...]
MacBook:~ xyz$ cd history2
MacBook:history2 xyz$ rails generate scaffold chancellor first_name last_name birthday:date day_of_death:date inauguration:date
[...]
MacBook:history2 xyz$ rake db:migrate
[...]
MacBook:history2 xyz$
Jetzt die
db/seeds.rb
mit den ersten sechs
Kanzlern anlegen:
Chancellor.create(:first_name => 'Konrad', :last_name => 'Adenauer', :birthday => '05.01.1876', :day_of_death => '19.04.1967', :inauguration => '15.09.1949')
Chancellor.create(:first_name => 'Ludwig', :last_name => 'Erhard', :birthday => '04.02.1897', :day_of_death => '05.05.1977', :inauguration => '16.10.1963')
Chancellor.create(:first_name => 'Kurt Georg', :last_name => 'Kiesinger', :birthday => '06.04.1904', :day_of_death => '09.03.1988', :inauguration => '01.12.1966')
Chancellor.create(:first_name => 'Willy', :last_name => 'Brandt', :birthday => '18.12.1913', :day_of_death => '08.10.1992', :inauguration => '21.10.1969')
Chancellor.create(:first_name => 'Walter', :last_name => 'Scheel', :birthday => '08.09.1919', :inauguration => '07.05.1974')
Chancellor.create(:first_name => 'Helmut', :last_name => 'Schmidt', :birthday => '23.12.1918', :inauguration => '16.05.1974')
Und diese Daten einspielen:
MacBook:history2 xyz$ rake db:seed
MacBook:history2 xyz$
Da wir nur
index
und
show
benötigen, sollten wir die nicht
benötigten Views löschen:
MacBook:history2 xyz$ rm app/views/chancellors/_form.html.erb
MacBook:history2 xyz$ rm app/views/chancellors/new.html.erb
MacBook:history2 xyz$ rm app/views/chancellors/edit.html.erb
MacBook:history2 xyz$
Die Datei
app/controllers/chancellors_controller.rb
können
wir mit einem Editor vereinfachen. Sie muss so aussehen:
class ChancellorsController < ApplicationController
# GET /chancellors
def index
@chancellors = Chancellor.all
end
# GET /chancellors/1
def show
@chancellor = Chancellor.find(params[:id])
end
end
Da wir nur HTML und keine JSON-Ausgabe benötigen, können wir uns
das respond_to do |format|
Konstrukt sparen. Rails wird
dann automatisch HTML rendern.
Wir brauchen nur die Routen für
index
und
show
. Bitte öffnen Sie die Datei
config/routes.rb
und ändern Sie sie wie folgt
ab:
History2::Application.routes.draw do
resources :chancellors, :only => [ :index, :show ]
end
Ein
rake routes zeigt uns, dass wirklich nur
noch
index
und
show
geroutet werden:
MacBook:history2 xyz$ rake routes
chancellors GET /chancellors(.:format) chancellors#index
chancellor GET /chancellors/:id(.:format) chancellors#show
MacBook:history2 xyz$
Wenn wir jetzt mit
rails server den Server
starten und die URL
http://0.0.0.0:3000/chancellors
aufrufen, bekommen wir eine Fehlermeldung:
MacBook:history2 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 22:46:28] INFO WEBrick 1.3.1
[2012-05-08 22:46:28] INFO ruby 1.9.3 (2012-04-20) [x86_64-darwin11.3.0]
[2012-05-08 22:46:28] INFO WEBrick::HTTPServer#start: pid=43440 port=3000
Started GET "/chancellors" for 127.0.0.1 at 2012-05-08 22:46:41 +0200
Processing by ChancellorsController#index as HTML
Chancellor Load (0.1ms) SELECT "chancellors".* FROM "chancellors"
Rendered chancellors/index.html.erb within layouts/application (17.6ms)
Completed 500 Internal Server Error in 81ms
ActionView::Template::Error (undefined method `edit_chancellor_path' for #<#<Class:0x007fc9150437c0>:0x007fc915047b18>):
20: <td><%= chancellor.day_of_death %></td>
21: <td><%= chancellor.inauguration %></td>
22: <td><%= link_to 'Show', chancellor %></td>
23: <td><%= link_to 'Edit', edit_chancellor_path(chancellor) %></td>
24: <td><%= link_to 'Destroy', chancellor, confirm: 'Are you sure?', method: :delete %></td>
25: </tr>
26: <% end %>
app/views/chancellors/index.html.erb:23:in `block in _app_views_chancellors_index_html_erb__3473545449794762094_70250803843160'
app/views/chancellors/index.html.erb:15:in `each'
app/views/chancellors/index.html.erb:15:in `_app_views_chancellors_index_html_erb__3473545449794762094_70250803843160'
Rendered /Users/xyz/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/_trace.erb (27.7ms)
Rendered /Users/xyz/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb (1.5ms)
Rendered /Users/xyz/.rvm/gems/ruby-1.9.3-p194/gems/actionpack-3.2.3/lib/action_dispatch/middleware/templates/rescues/template_error.erb within rescues/layout (40.6ms)
Die Fehlermeldung sagt, dass wir im View
app/views/chancellors/index.html.erb
eine Methode
edit_chancellor_path
aufrufen. Da wir aber nur
noch
index
und
show
routen, gibt es keine
edit
-,
destroy
- oder
new
-Methoden mehr. Wir müssen entsprechend die
Datei
app/views/chancellors/index.html.erb
im
Editor wie folgt anpassen:
<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>
</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>
</tr>
<% end %>
</table>
Und wo wir schon gerade dabei sind, ändern wir auch noch die
app/views/chancellors/show.html.erb
entsprechend
ab:
<p>
<b>First name:</b>
<%= @chancellor.first_name %>
</p>
<p>
<b>Last name:</b>
<%= @chancellor.last_name %>
</p>
<p>
<b>Birthday:</b>
<%= @chancellor.birthday %>
</p>
<p>
<b>Day of death:</b>
<%= @chancellor.day_of_death %>
</p>
<p>
<b>Inauguration:</b>
<%= @chancellor.inauguration %>
</p>
Anmerkung
Bei diesem Beispiel gehe ich nicht auf notwendige Veränderungen
in den Tests ein, da dies keine Übung zum Test-Driven-Development ist,
sondern eine Arbeitsweise mit Scaffolding aufzeigen soll.
TDD-Entwickler werden schnell die Tests anpassen können.