Neu: Rails Schulungen in Deutschland vom Autor dieses Buches.div class="para">Wenn Sie eine Zeit lang mit Rails gearbeitet haben, werden Sie nach jedem Aufruf von rails generate scaffold oder rails generate model immer gleiche Änderungen machen. Sie werden das Scaffold an Ihre Bedürfnisse anpassen. Glücklicherweise können Sie die von Rails benutzten Templates für die Erstellung der Controller oder Model Dateien durch eigene Templates ersetzen. Damit lässt sich sehr viel Zeit einsparen.

Ich zeige Ihnen anhand des Controllers und des Model Templates, wie die prinzipielle Vorgehensweise ist.

Tipp

15 Minuten Optimierung eines Templates an Ihre Bedürfnisse spart Ihnen bei jedem Rails-Projekt später Stunden an Arbeitszeit!

Scaffold Controller Template

Nehmen wir einmal an, Sie möchten ein Scaffold User anlegen:
Stefan-Wintermeyers-MacBook-Air:webshop xyz$ rails generate scaffold User first_name last_name login
      [...]
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      [...]
Stefan-Wintermeyers-MacBook-Air:webshop xyz$
Der per Default generierte Controller app/controllers/users_controller.rb sieht dann in Rails 3.2 so aus:
class UsersController < ApplicationController
  # GET /users
  # GET /users.json
  def index
    @users = User.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @users }
    end
  end

  # GET /users/1
  # GET /users/1.json
  def show
    @user = User.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @user }
    end
  end

  # GET /users/new
  # GET /users/new.json
  def new
    @user = User.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @user }
    end
  end

  # GET /users/1/edit
  def edit
    @user = User.find(params[:id])
  end

  # POST /users
  # POST /users.json
  def create
    @user = User.new(params[:user])

    respond_to do |format|
      if @user.save
        format.html { redirect_to @user, notice: 'User was successfully created.' }
        format.json { render json: @user, status: :created, location: @user }
      else
        format.html { render action: "new" }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /users/1
  # PUT /users/1.json
  def update
    @user = User.find(params[:id])

    respond_to do |format|
      if @user.update_attributes(params[:user])
        format.html { redirect_to @user, notice: 'User was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @user.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /users/1
  # DELETE /users/1.json
  def destroy
    @user = User.find(params[:id])
    @user.destroy

    respond_to do |format|
      format.html { redirect_to users_url }
      format.json { head :no_content }
    end
  end
end
Wenn wir aber nur HTML und gar kein JSON benötigen, dann könnte diese Datei auch so aussehen:
class UsersController < ApplicationController
  def index
    @users = User.all
  end

  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def edit
    @user = User.find(params[:id])
  end

  def create
    @user = User.new(params[:user])

    if @user.save
      redirect_to @user, notice: 'User was successfully created.'
    else
      render action: "new"
    end
  end

  def update
    @user = User.find(params[:id])

    if @user.update_attributes(params[:user])
      redirect_to @user, notice: 'User was successfully updated.'
    else
      render action: "edit"
    end
  end

  def destroy
    @user = User.find(params[:id])
    @user.destroy

    redirect_to users_url
  end
end
Das original Template, welches von rails generate scaffold zum Generieren des Controllers benutzt wird, finden Sie im Rails Github Repository unter https://github.com/rails/rails/blob/3-2-stable/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb.
Es ist eine normale ERB-Datei, die Sie downloaden und dann als neue Datei lib/templates/rails/scaffold_controller/controller.rb (die entsprechenden Verzeichnisse müssen Sie evt. von Hand anlegen) abspeichern können. Um das obige Wunschergebnis zu bekommen, müssen Sie das Template wie folgt abändern:
<% if namespaced? -%>
require_dependency "<%= namespaced_file_path %>/application_controller"

<% end -%>
<% module_namespacing do -%>
class <%= controller_class_name %>Controller < ApplicationController
  def index
    @<%= plural_table_name %> = <%= orm_class.all(class_name) %>
  end

  def show
    @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
  end

  def new
    @<%= singular_table_name %> = <%= orm_class.build(class_name) %>
  end

  def edit
    @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
  end

  def create
    @<%= singular_table_name %> = <%= orm_class.build(class_name, "params[:#{singular_table_name}]") %>

    if @<%= orm_instance.save %>
      redirect_to @<%= singular_table_name %>, <%= key_value :notice, "'#{human_name} was successfully created.'" %>
    else
      render <%= key_value :action, '"new"' %>
    end
  end

  def update
    @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>

    if @<%= orm_instance.update_attributes("params[:#{singular_table_name}]") %>
      redirect_to @<%= singular_table_name %>, <%= key_value :notice, "'#{human_name} was successfully updated.'" %>
    else
      render <%= key_value :action, '"edit"' %>
    end
  end

  def destroy
    @<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
    @<%= orm_instance.destroy %>

    redirect_to <%= index_helper %>_url
  end
end
<% end -%>
Jetzt bekommen Sie bei jeder Benutzung von rails generate scaffold den Controller in der von Ihnen gewünschten Variante.

Model Template

Der Grundgedanke ist der gleiche wie beim Controller in „Scaffold Controller Template“: Es gilt, das vom Rails Generator angelegte Model an die eigenen Bedürfnisse anzupassen. Das von rails generate model und damit auch von rails generate scaffold benutzte Model Template finden Sie im Rails Github Repository unter https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/rails/generators/active_record/model/templates/model.rb.
Speichern Sie diese Datei in Ihrem Rails-Projekt unter lib/templates/active_record/model/model.rb ab. Wenn Sie die Methode to_s per Default verändern möchten, so könnte Ihre model.rb z. B. so aussehen:
<% module_namespacing do -%>
class <%= class_name %> < <%= parent_class_name.classify %>
<% attributes.select {|attr| attr.reference? }.each do |attribute| -%>
  belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %>
<% end -%>
<% if !accessible_attributes.empty? -%>
  attr_accessible <%= accessible_attributes.map {|a| ":#{a.name}" }.sort.join(', ') %>
<% else -%>
  # attr_accessible :title, :body
<% end -%>

  def to_s
    <%- if attributes.map{ |a| a.name }.include?('name') -%>
    name
    <%- else -%>
    "<%= class_name %> #{id}"
    <%- end -%>
  end

end
<% end -%>
Wenn Sie jetzt ein neues Model mit rails generate model Book name number_of_pages:integer anlegen, wird die Datei app/models/book.rb wie folgt aussehen:
class Book < ActiveRecord::Base
  attr_accessible :name, :number_of_pages

  def to_s
    name
  end

end

Autor

Stefan Wintermeyer