Scaffolding (Teil 3)

Scaffolding-Code generieren:

Codegenerierung ist die andere wichtige Form des Scaffolding. Sie generieren das Scaffolding mit dem Befehl ruby script/generate scaffold.

Führen Sie es ohne Parameter aus, um eine Beschreibung des Generators und die von ihm verwendeten Parameter zu erhalten:

> ruby script/generate scaffold
Usage: script/generate scaffold ModelName [ControllerName] [action, …]

General Options:
    -p, –pretend        Run but do not make any changes.

    -f, –force          Overwrite files that already exist.
    -s, –skip           Skip files that already exist.

    -q, –quiet          Suppress normal output.
    -t, –backtrace      Debugging: show backtrace on errors.

    -h, –help           Show this help message.
    -c, –svn            Modify files with subversion. (Note: svn must be in path)

Description:
    The scaffold generator creates a controller to interact with a model.

Sie müssen den Namen eines Modells und eines Controllers angeben. Um also das Scaffolding für den Controller und die Views unseres Photo-Modells zu generieren, müssen Sie Folgendes eingeben:

ruby script/generate scaffold photo photos

Antworten Sie mit y, wenn Sie von Rails gefragt werden, ob Dateien ersetzt werden sollen. Wenn Sie den Namen des Controllers weglassen, verwendet Rails den englischen Plural des Modellnamens. Um also das Scaffolding für slides, slideshows und categories zu generieren, geben Sie Folgendes ein:

ruby script/generate scaffold slide
ruby script/generate scaffold slideshow

ruby script/generate scaffold category

Warum Scaffolding Controller-Namen pluralisiert

Wenn Sie das Scaffolding wie folgt ausführen:

ruby script/generate scaffold Photo

erhalten Sie ein Modell namens Photo und einen Controller namens PhotosController. Sie bekommen dieses Verhalten, weil der Scaffolding-Generator zwei Parameter verlangt: das Modell und den Controller. Lassen Sie den Controller weg, pluralisiert der Generator den Namen. Oft ist das genau das, was Sie wollen, weil Rails-Controller häufig mit Kollektionen von Dingen umgehen.

Üblicherweise wollen Sie einen singulären Modellnamen. Zum Beispiel könnten Sie einen Administrations-Controller namens Admin benötigen. Wenn Sie normalerweise mit Pluralformen arbeiten, können Sie den Namen des Controllers weglassen. Wünschen Sie einen Controllernamen im Singular, müssen Sie sowohl den Modell- als auch den Controller-Namen angeben. Weitere Informationen erhalten Sie über die Scaffolding-Hilfe, wenn Sie Folgendes eingeben:

ruby script/generate scaffold

Der generierte Code

Sehen wir uns den von Rails erzeugten Controller an. Ihr Code könnte etwas anders aussehen als der hier abgebildete, das Prinzip sollte aber das gleiche sein. Öffnen Sie apps/controllers/photos_controller.rb:

class PhotosController < ApplicationController

  def index
    list
    render :action => ‚list‘

  end
  def list

    @photo_pages, @photos = paginate :photos, :per_page => 10

  end
  def show
    @photo = Photo.find(params[:id])

  end

  def new
    @photo = Photo.new

  end
  def create

    @photo = Photo.new(params[:photo])

    if @photo.save
      flash[:notice] = ‚Photo angelegt.‘

      redirect_to :action => ‚list‘
    else
      render :action => ’new‘

    end
  end
  def edit

    @photo = Photo.find(params[:id])
  end
  def update
    @photo = Photo.find(params[:id])
    if @photo.update_attributes(params[:photo])

      flash[:notice] = ‚Photo aktualisiert.‘
      redirect_to :action => ’show‘, :id => @photo

    else
      render :action => ‚edit‘
    end

  end
  def destroy

    Photo.find(params[:id]).destroy

    redirect_to :action => ‚list‘
  end
end

Wie Sie sehen, generiert Rails einen Controller für jede Methode aus Tabelle 4-1. Gehen Sie mit Ihrem Browser auf http://localhost:3000/photos und überprüfen Sie, dass der generierte Code sich genauso verhält wie der durch die scaffold :photo-Methode generierte Code.

Dennoch weicht der Code leicht ab. Statt die Views innerhalb des Controllers zu generieren, wie das die scaffold-Methode tut, enthält der Code explizit gerenderte Views in rhtml-Code. Sehen wir uns einen dieser Views an. Öffnen Sie app/views/photos/list.rhtml:

1 <% for column in Photo.content_columns %>

2 <p>

3   <b><%= column.human_name %>:</b> <%=h @photo.send(column.name) %>

4 </p>
5 <% end %>
6
7 <%= link_to ‚Bearbeiten‘, :action => ‚edit‘, :id => @photo %> |

8 <%= link_to ‚Zur&uuml;ck‘, :action => ‚list‘ %>

Dieser View wurde von der list-Methode von PhotosController erzeugt. Sehen wir uns die erste und dritte Zeile genauer an:

<% for column in Photo.content_columns %>
In der ersten Zeile geht der View jede Spalte der Datenbank durch. Vergessen Sie nicht, dass Active Record Metadaten in Photo eingefügt hat, das auch ein Array mit jeder Spalte der Tabelle umfasst. content_columns enthält alle Spalten, die für die öffentliche Ausgabe vorgesehen sind. (Sie sehen beispielsweise weder Fremdschlüssel noch die id.)

<b><%= column.human_name %>
Der View enthält einen freundlichen Namen, der als Label für das Element dient.
<%=h @photo.send(column.name) %>
Der View sendet eine Nachricht mit dem Namen der Spalte an @photo und rendert das Ergebnis. (Zum Beispiel wäre @photo.send „filename“ identisch mit @photo.filename.)

Abbildung 4-5 zeigt das Ergebnis. Der View führt alle Eigenschaften eines Photo-Datensatzes in der Datenbank auf. Die Dateinamen-Eigenschaft war von Anfang an in der Datenbank enthalten. Die Eigenschaften Erzeugt am, Thumbnail und Beschreibung wurden bereits in diesem Kapitel mit Hilfe einer Migration eingefügt. Würden wir weitere Eigenschaften hinzufügen, müssten wir im list.rhtml-View keinerlei Änderungen vornehmen, um sie mit auszugeben.

Abbildung 4-5
Dieser show-View ist dynamisch

Der show.rhtml-View spiegelt Änderungen in der Datenbank wider. Sehen wir uns nun einen View an, der etwas weniger dynamisch ist. Öffnen Sie app/views/photos/_form. rhtml:

<%= error_messages_for ‚photo‘ %>
<!–[form:photo]–>

<p><label for=“photo_created_at“>Erzeugt am</label><br/>
<%= datetime_select ‚photo‘, ‚created_at‚  %></p>

<p><label for=“photo_filename“>Dateiname</label><br/>
<%= text_field ‚photo‘, ‚filename‘  %></p>

<p><label for=“photo_thumbnail“>Thumbnail</label><br/>
<%= text_field ‚photo‘, ‚thumbnail‚  %></p>

<p><label for=“photo_description“>Beschreibung</label><br/>
<%= text_field ‚photo‘, ‚description‘  %></p>

<!–[eoform:photo]–>

Dies ist ein so genannter partieller View, und er ist für die Ausgabe eines Formulars für ein Photo in edit.rhtml und new.rhtml verantwortlich. (Sie erfahren im nächsten Kapitel mehr über partielle Views.) Die fett gedruckten Wörter sind Attribute von Photo. Weil wir zur Ausgabe des Formulars expliziten Code generiert haben, funktioniert dieser View nur mit Datenbankspalten, die bereits vorhanden waren, als wir das Scaffolding generiert haben. Hier sehen Sie einen der primären Unterschiede zwischen Scaffolding mittels Metaprogrammierung und codegeneriertem Scaffolding. Wenn Sie mit Metaprogrammierung arbeiten, spiegelt das Scaffolding Änderungen in der Datenbank wider, weil unsere scaffold :photo-Methode den Code zur Laufzeit generiert. Mit dem generierten Code erhalten wir durch das Scaffolding einen einmaligen Vorteil, müssen ihn nachfolgend aber auch pflegen.

Das Beste beider Welten

Die meisten Rails-Entwickler nutzen beide Arten des Scaffolding. Die scaffold-Methode ist hilfreich, wenn sich Ihre Active Record-Modelle schnell ändern, weil sie Änderungen an der Datenbank in der Benutzerschnittstelle wiedergibt. Später können Sie das Scaffolding nutzen und Controller und Benutzerschnittstellen mit der Zeit weiter ausbauen, wobei Sie den generierten Code als Grundlage verwenden. Die Kombination dieser beiden Techniken ist eine äußerst leistungsstarke Vorgehensweise.

Scaffolding hat aber auch seine Grenzen. Sie erhalten für jeden Zweck ein und dieselbe Benutzerschnittstelle und einen Controller. Dieser ist nicht für jeden Zweck geeignet und auch nicht vollständig. Eine der größten Schwächen des Scaffolding ist das fehlende Beziehungsmanagement. Das Scaffolding berücksichtigt bei der Codegenerierung keine Beziehungen im existierenden Modell.

Was kommt jetzt?

In diesem Kapitel haben wir Scaffolding für eine einfache Benutzerschnittstelle generiert. Aber der Scaffolding-Code hat seine Grenzen. Er berücksichtigt keine Beziehungen, d.h. Sie können die mit einer Kategorie verknüpften Photos weder sehen noch editieren, ebenso wenig die Dias in einer Diashow. Die Views sind darüber hinaus hässlich und unvollständig. Im nächsten Kapitel wollen wir diesen Problemen abhelfen. Wir verwenden das generierte Scaffolding als Basis und bauen eine umfassendere Benutzerschnittstelle auf. Photo Share entwickelt sich schnell, und so geht es auch weiter.

1Wenn Sie nicht mit uns zusammen codiert haben, nun aber damit anfangen wollen, können Sie sich den Code bis Kapitel 3 von der Webseite zum Buch (http://www.oreilly.com/catalog/rubyrails) herunterladen.

2Sie finden die eigentliche Definition im Rails-Quellcode. scaffold ist tatsächlich in ClassMethods definiert und wird als Modul in ActionController eingebunden.

Dieses Tutorial stammt aus dem Buch „Durchstarten mit Rails“ aus dem O’Reilly Verlag.
Details zu dem Buch

Alle drei Teile dieser Scaffolding-Serie steht unseren Leseren auch als PDF zur Verfügung: Downloadlink: Scaffolding_Kap4.pdf

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.