<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ASCIIcasts - Full Episode Feed</title>
    <description>The latest episodes from ASCIIcasts</description>
    <link>http://asciicasts.com/</link>
    <pubDate>Thu, 09 Sep 2010 18:22:59 +0000</pubDate>
    <ttl>1440</ttl>
    <item>
      <title>Controller in Rails 3</title>
      <description>&lt;p&gt;W&amp;auml;hrend die wichtigsten &amp;Auml;nderungen an den Rails 3-Controllern im Hintergrund passiert sind, gibt es auch einige &amp;Auml;nderungen an der &amp;ouml;ffentlichen API, mit welcher wir als Rails-Entwickler interagieren. Diese Episode wird einige der neuen Features behandeln.&lt;/p&gt;

&lt;h3&gt;Parameter Logging&lt;/h3&gt;

&lt;p&gt;Die erste &amp;Auml;nderung betrifft den &lt;code&gt;ApplicationController&lt;/code&gt;. In einer Rails 2 Applikation kann man bestimmte Parameter filtern, sodass sie nicht in Klartext im Logfile stehen, indem man die &lt;code&gt;filter_parameter_logging&lt;/code&gt;-Methode, wie hier gezeigt, benutzt:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/application_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class ApplicationController &amp;lt; ActionController::Base
  protect_from_forgery
  filter_parameter_logging :password
end
&lt;/pre&gt;

&lt;p&gt;Diese Methode wurde in Rails 3 als deprecated markiert und sollte aus Anwendungen entfernt werden. Der Parameterfilter wird nun in der neuen &lt;code&gt;config/application.rb&lt;/code&gt;-Datei konfiguriert. Der Parameterfiltercode, befindet sich am Ende der Datei.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/config/application.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
# Configure sensitive parameters which will be filtered from the log file.
config.filter_parameters += [:password]
&lt;/pre&gt;

&lt;p&gt;Diese Zeile wird standardm&amp;auml;&amp;szlig;ig zu einer neuen Rails 3 Anwendung hinzugef&amp;uuml;gt. Man vergisst leicht, das Filtern zu aktivieren, deswegen ist es ein hilfreiches Feature, dass es automatisch aktiviert ist. Nat&amp;uuml;rlich wird es nur Passwortparameter filtern und muss abge&amp;auml;ndert werden, wenn andere Parameter, zum Beispiel Kreditkartennummern, gefiltert werden sollen.&lt;/p&gt;

&lt;h3&gt;Redirect-Kurzformen&lt;/h3&gt;

&lt;p&gt;Als n&amp;auml;chstes werfen wir ein Blick auf den &lt;code&gt;ProductsController&lt;/code&gt; einer Store-Anwendung. Wenn wir uns den Code f&amp;uuml;r die &lt;code&gt;create&lt;/code&gt;-Methode anschauen, sehen wir, dass, sobald ein valides Produkt gespeichert wurde, die Action eine Flash-Nachricht erstellt und dann zur &lt;code&gt;show&lt;/code&gt;-Action f&amp;uuml;r das neu erstellte Produkt weiterleitet.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    flash[:notice] = &amp;quot;Successfully created product.&amp;quot;
    redirect_to @product
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Dies ist das ganz normale Verhalten in einem Controller und in Rails 3 k&amp;ouml;nnen wir diese zwei Zeilen kombinieren, sodass die Flash-Nachricht ein Parameter der &lt;code&gt;redirect_to&lt;/code&gt;-Methode wird.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    redirect_to @product, :notice =&amp;gt; &amp;quot;Successfully created product.&amp;quot;
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
  end
end
&lt;/pre&gt;

&lt;p&gt;Sowohl &lt;code&gt;:notice&lt;/code&gt; als auch &lt;code&gt;:alert&lt;/code&gt; funktionieren hier, jeder andere Flash-Nachrichtentyp muss in einem &lt;code&gt;:flash&lt;/code&gt;-Hash eingebettet werden, was man aber eher selten ben&amp;ouml;tigt. Dieses Feature wurde auch zu Rails 2.3.6 hinzugef&amp;uuml;gt, damit man diesen Kurzform auch mit einer aktuellen Rails 2 Version nutzen kann.&lt;/p&gt;

&lt;p&gt;Die &lt;code&gt;redirect_to&lt;/code&gt;-Methode nimmt auch ein Model-Objekt als Parameter. Ein Produkt-Model-Objekt als &lt;code&gt;@product&lt;/code&gt; zu &amp;uuml;bergeben ist eine Kurzform f&amp;uuml;r &lt;code&gt;@product_path(@product)&lt;/code&gt; und wird in den Pfad der &lt;code&gt;show&lt;/code&gt;-Action f&amp;uuml;r das Produkt &amp;uuml;bersetzt. Wenn wir stattdessen zur edit-Seite dieses&amp;#x27; Produkts weiterleiten wollen, k&amp;ouml;nnen wir &lt;code&gt;edit_product_path(@product)&lt;/code&gt; nutzen. Es gibt allerdings noch eine weitere n&amp;uuml;tzliche Kurzform. Anstatt&lt;/p&gt;

&lt;pre class="ruby"&gt;
redirect_to edit_product_path(@product)
&lt;/pre&gt;

&lt;p&gt;k&amp;ouml;nnen wir es als Array schreiben:&lt;/p&gt;

&lt;pre class="ruby"&gt;
redirect_to [:edit, @product]
&lt;/pre&gt;

&lt;p&gt;Dies wird in denselben edit_product_path &amp;uuml;bersetzt, aber mit etwas weniger Code. Wie die obige &lt;code&gt;:notice&lt;/code&gt;-Option, funktioniert das auch in einer neueren Version von Rails 2. Diese Kurzform funktioniert auch mit verschachtelten Ressourcen, somit k&amp;ouml;nnen wir, wenn ein Produkt zu einer Kategorie geh&amp;ouml;rt, folgenderma&amp;szlig;en weiterleiten:&lt;/p&gt;

&lt;pre class="ruby"&gt;
redirect_to [@category, @product]
&lt;/pre&gt;

&lt;p&gt;Diese Array-Technik funktioniert &amp;uuml;berall wo man eine URL generieren kann und kann genauso gut in dem View-Code einer &lt;code&gt;link_to&lt;/code&gt;-Methode oder in Controllern benutzt werden.&lt;/p&gt;

&lt;h3&gt;Permanente Cookies&lt;/h3&gt;

&lt;p&gt;Das n&amp;auml;chste neue Feature sind permanente Cookies. Angenommen ein Benutzer erstellt ein neues Produkt, dann wollen wir die Produkt-ID in einem Cookie speichern. Wir k&amp;ouml;nnen die &lt;code&gt;cookies&lt;/code&gt;-Methode daf&amp;uuml;r benutzen:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/proucts_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    cookies[:last_product_id] = @product.id
    redirect_to @product, :notice =&amp;gt; &amp;quot;Successfully created product.&amp;quot;
  else
    render :action =&amp;gt; &amp;#x27;new&amp;#x27;
   end
end
&lt;/pre&gt;

&lt;p&gt;Dieser Code erstellt ein Session Cookie, welcher nur solange h&amp;auml;lt, wie der Benutzer sein Browserfenster offen h&amp;auml;lt. Um einen Cookie mit einem speziellem Ablauf-Datum in Rails 2 zu erstellen, m&amp;uuml;ssten wir den Wert in einen Hash umwandeln und ein explizites Ablaufdatum setzen:&lt;/p&gt;

&lt;pre class="ruby"&gt;
cookies[:last_product_id] = { :value =&amp;gt; @product_id, :expires =&amp;gt; 1.month.from_now }
&lt;/pre&gt;

&lt;p&gt;In Rails 3 (und ab Rails 2.3.6) k&amp;ouml;nnen wir die neue &lt;code&gt;cookies.permanent&lt;/code&gt;-Methode benutzen um einen Cookie mit langer Ablaufzeit zu erstellen.&lt;/p&gt;

&lt;pre class="ruby"&gt;
cookies.permanent[:last_product_id] = @product.id
&lt;/pre&gt;

&lt;p&gt;Wir k&amp;ouml;nnen au&amp;szlig;erdem gesignte Cookies auf diese Art erstellen, doch darauf gehen wir jetzt nicht im Detail ein. Es gibt einen sehr lesenswerten &lt;a href="http://m.onkey.org/2010/2/5/signed-and-permanent-cookies-in-rails-3"&gt;Blogeintrag&lt;/a&gt; von Pratik Naik zu diesem Thema. Im Wesentlichen nutzt man die &lt;code&gt;cookies.permanent.signed&lt;/code&gt;-Methode um einen verschl&amp;uuml;sselten Cookie zu generieren und ihn sp&amp;auml;ter zu lesen. Zu beachten ist, dass man ein &lt;code&gt;cookie_verifier_secret&lt;/code&gt; brauchen, damit die Anwendung funktioniert.&lt;/p&gt;

&lt;h3&gt;&lt;code&gt;respond_with&lt;/code&gt; benutzen&lt;/h3&gt;

&lt;p&gt;Die letzte neue Sache in dieser Episode, ist wahrscheinlich die bedeutendste Erg&amp;auml;nzung an Rails 3 Controllern: &lt;code&gt;respond_with&lt;/code&gt;. Wir werden das demonstrieren, indem wir ein REST-Service &amp;uuml;ber ein XML-Interface zu unserem &lt;code&gt;ProductsController&lt;/code&gt; hinzuf&amp;uuml;gen. Das bedeutet, dass jede Action des Controllers zus&amp;auml;tzlich zu seiner HTML Antwort eine XML-Antwort zur&amp;uuml;ckgeben muss.&lt;/p&gt;

&lt;p&gt;In einer Rails 2 Applikation w&amp;uuml;rden wir das mit der &lt;code&gt;respond_to&lt;/code&gt;-Methode in jeder Action implementieren:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def index
  @products = Product.all
  respond_to do |format|
    format.html
    format.xml { render :xml =&amp;gt; @products }
  end
end
&lt;/pre&gt;

&lt;p&gt;In dem &lt;code&gt;respond_to&lt;/code&gt;-Block legen wir f&amp;uuml;r alle Formate fest, wie die Action reagieren soll. F&amp;uuml;r eine XML-Anfrage soll sie, zum Beispiel, den @products-Array als XML darstellen. Diese Vorgehensweise kann schnell unhandlich werden, wenn wir dies f&amp;uuml;r jede Action im Controller machen m&amp;uuml;ssen.&lt;/p&gt;

&lt;p&gt;In Rails 3 k&amp;ouml;nnen wir diesen Code mit einem Aufruf von &lt;code&gt;respond_with&lt;/code&gt; ersetzen, dem wir das bestimmte Objekt mitgeben, in diesem Fall der Array von Produkten. Damit &lt;code&gt;respond_with&lt;/code&gt; funktioniert, m&amp;uuml;ssen wir die &amp;quot;Schwester&amp;quot;-Klassenmethode &lt;code&gt;respond_to&lt;/code&gt; benutzen, um festzulegen, auf welche MIME-Typen der Controller reagieren soll und somit &lt;code&gt;respond_with&lt;/code&gt; wei&amp;szlig;, welche Formate es in jeder Action zur&amp;uuml;ckgeben kann.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class ProductsController &amp;lt; ApplicationController
  respond_to :html, :xml

  def index
    @products = Product.all
    respond_with @products
  end

  # Other methods
end
&lt;/pre&gt;

&lt;p&gt;Wenn wir unsere &amp;Auml;nderungen testen wollen und uns die Produktindexseite im Browser anschauen, sehen wir, das die HTML-index-Action so angezeigt wird, wie wir es erwartet haben.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/433/original/E224I01.png" width="800" height="333" alt="Die Produktindexseite."/&gt;
&lt;/div&gt;

&lt;p&gt;Und wenn wir &lt;code&gt;.xml&lt;/code&gt; an die URL anh&amp;auml;ngen, bekommen wir die XML-Antwort.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/434/original/E224I02.png" width="801" height="199" alt="Die Produktindexseite als XML."/&gt;
&lt;/div&gt;

&lt;p&gt;Wie funktioniert nun die &lt;code&gt;respond_with&lt;/code&gt;-Methode genau? F&amp;uuml;r einen einfachen GET-Request (z.B. &lt;code&gt;index&lt;/code&gt;) sucht es nach einer View-Datei zur Darstellung des passenden MIME-Typs, beispielsweise eine &lt;code&gt;.html.erb&lt;/code&gt;-Datei, und rendert es. Falls &lt;code&gt;respond_with&lt;/code&gt; keinen View finden kann, versucht es eine Methode wie &lt;code&gt;to_xml&lt;/code&gt; (oder z.B. &lt;code&gt;to_json&lt;/code&gt;) aufzurufen, um das &amp;uuml;bergebene Objekt im passenden Format darzustellen.&lt;/p&gt;

&lt;p&gt;Mit diesem Wissen k&amp;ouml;nnen wir diese respond_with-Zeile einfach in die &lt;code&gt;show&lt;/code&gt;- und die &lt;code&gt;new&lt;/code&gt;-Methode kopieren.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controller/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def show
  @product = Product.find(params[:id])
  respond_with @product
end

def new
  @product = Product.new
  respond_with @product
end
&lt;/pre&gt;

&lt;p&gt;Die &lt;code&gt;create&lt;/code&gt;-Action ist etwas komplizierter, denn sie enth&amp;auml;lt HTML-spezifischen Code wie redirect_to und &lt;code&gt;render&lt;/code&gt;. Wir wollen diese Methoden nicht in einem XML-Response verwenden. Und wir k&amp;ouml;nnen beide vermeiden, indem wir sie einfach entfernen und stattdessen einen Aufruf zu &lt;code&gt;respond_with&lt;/code&gt; hinzuf&amp;uuml;gen. Die Action sieht jetzt wie folgt aus:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def create
  @product = Product.new(params[:product])
  if @product.save
    cookies[:last_product_id] = @product.id
    flash[:notice] = &amp;quot;Successfully created product.&amp;quot;
  end
  respond_with(@product)
end
&lt;/pre&gt;

&lt;p&gt;Wir k&amp;ouml;nnen das machen, weil &lt;code&gt;respond_with&lt;/code&gt; &amp;uuml;berpr&amp;uuml;ft, ob das &amp;uuml;bergebene Objekt valide ist oder nicht, und je nachdem rendert oder redirectet. Jetzt k&amp;ouml;nnen wir &lt;code&gt;respond_with&lt;/code&gt; zu den anderen Actions im Controller hinzuf&amp;uuml;gen und dabei wieder jeden HTML-spezifischen Code entfernen. Danach sieht unsere Controller-Code etwa so aus:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
class ProductsController &amp;lt; ApplicationController
  respond_to :html, :xml

  def index
    @products = Product.all
    respond_with @products
  end

  def show
    @product = Product.find(params[:id])
    respond_with @product
  end

  def new
    @product = Product.new
    respond_with @product
  end

  def create
    @product = Product.new(params[:product])
    if @product.save
      cookies[:last_product_id] = @product.id
      flash[:notice] = &amp;quot;Successfully created product.&amp;quot;
    end
    respond_with(@product)
  end
  
  def edit
    @product = Product.find(params[:id])
    respond_with(@product)
  end
  
  def update
    @product = Product.find(params[:id])
    if @product.update_attributes(params[:product])
      flash[:notice] = &amp;quot;Successfully updated product.&amp;quot;
    end
    respond_with(@product)
  end

  def destroy
    @product = Product.find(params[:id])
    @product.destroy
    flash[:notice] = &amp;quot;Successfully destroyed product.&amp;quot;
    respond_with(@product)
  end
end
&lt;/pre&gt;

&lt;p&gt;Die &lt;code&gt;respond_with&lt;/code&gt;-Methode kann etwas verwirrend sein, deswegen hier eine kleine Zusammenfassung:&lt;/p&gt;

&lt;p&gt;F&amp;uuml;r einen GET-Request sucht &lt;code&gt;respond_with&lt;/code&gt; zuerst nach einem View, welcher zu diesem spezifischen Format passt. Wenn es einen findet, rendert er den View; wenn nicht, ruft es &lt;code&gt;to_xml&lt;/code&gt; (oder was auch immer f&amp;uuml;r ein Format angefordert wurde) auf dem &amp;uuml;bergebenen Objekt auf.&lt;/p&gt;

&lt;p&gt;F&amp;uuml;r jeden anderen Requesttyp pr&amp;uuml;ft &lt;code&gt;respond_with&lt;/code&gt;, ob das &amp;uuml;bergebene Objekt Errors hat. Wenn es welche hat, wird der passende View gerendert (z.B. &lt;code&gt;new&lt;/code&gt; f&amp;uuml;r die &lt;code&gt;create&lt;/code&gt;-Action und &lt;code&gt;edit&lt;/code&gt; f&amp;uuml;r &lt;code&gt;update&lt;/code&gt;). Falls es keine gibt, redirectet es zu der objektspezifischen Seite (z.B. die &lt;code&gt;show&lt;/code&gt;-Action).&lt;/p&gt;

&lt;p&gt;Wird k&amp;ouml;nnen es ausprobieren, indem wir eines unserer Produkte bearbeiten.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/435/original/E224I03.png" width="800" height="378" alt="Bearbeiten eines Produkts."/&gt;
&lt;/div&gt;

&lt;p&gt;Wenn wir den &amp;quot;Update Product&amp;quot; Button dr&amp;uuml;cken, wird die &lt;code&gt;update&lt;/code&gt;-Action aufgerufen und &lt;code&gt;respond_with&lt;/code&gt; f&amp;uuml;hrt eine Weiterleitung zur Seite des Produktes durch. Das Produkt wurde erfolgreich aktualisiert.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/436/original/E224I04.png" width="800" height="358" alt="The product has been successfully updated."/&gt;
&lt;/div&gt;

&lt;p&gt;Genauso klappt der &amp;quot;Destroy&amp;quot; Link, wir werden zur Indexseite weitergeleitet.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/437/original/E224I05.png" width="801" height="337" alt="respond_with leitet zur Indexseite weiter, nachdem ein Produkt gel&amp;ouml;scht wurde."/&gt;
&lt;/div&gt;

&lt;p&gt;Wenn das Standardverhalten von &lt;code&gt;respond_with&lt;/code&gt; f&amp;uuml;r einige Teile unserer Anwendung nicht mehr ausreicht, k&amp;ouml;nnen wir es f&amp;uuml;r bestimmte Actions anpassen. Zum Beispiel, wenn wir wollen, dass bei dem Update eines Produktes, die Anwendung nicht zur &lt;code&gt;show&lt;/code&gt;-Action, sondern zur &lt;code&gt;index&lt;/code&gt;-Action weiterleiten soll. In diesem Fall k&amp;ouml;nnen wir &lt;code&gt;respond_with&lt;/code&gt; eine location-Option &amp;uuml;bergeben:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def update
  @product = Product.find(params[:id])
  if @product.update_attributes(params[:product])
    flash[:notice] = &amp;quot;Successfully updated product.&amp;quot;
  end
  respond_with(@product, :location =&amp;gt; products_url)
end
&lt;/pre&gt;

&lt;p&gt;Wir k&amp;ouml;nnen auch die jeweiligen Formate &amp;uuml;berschreiben, indem wir &lt;code&gt;respond_with&lt;/code&gt; einen Block &amp;uuml;bergeben, genauso wie wir es mit der &lt;code&gt;respond_to&lt;/code&gt;-Methode machen w&amp;uuml;rden. Wenn wir zum Beispiel einfach nur etwas Text f&amp;uuml;r das XML-Format der edit-Action darstellen wollen, k&amp;ouml;nnen wir es so machen:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/controllers/products_controller.rb&lt;/p&gt;
&lt;pre class="ruby"&gt;
def edit
  @product = Product.find(params[:id])
  respond_with(@product) do |format|
    format.xml { render :text =&amp;gt; &amp;quot;I&amp;#x27;m XML!&amp;quot; }
  end
end
&lt;/pre&gt;

&lt;p&gt;Wenn wir die XML-Version der edit-Seite besuchen, sehen wir den Text.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/438/original/E224I06.png" width="799" height="140" alt=" Die edit-Seite zeigt eigenes XML."/&gt;
&lt;/div&gt;

&lt;p&gt;Sollte man letztendlich eine komplett eigene Anpassung ben&amp;ouml;tigen, kann man eine eigene Responder-Klasse &amp;uuml;bergeben. Auf diese Weise wird der Controller alles an diese Klasse weiterreichen und wir k&amp;ouml;nnen das Verhalten des Responses frei anpassen.&lt;/p&gt;

&lt;pre class="ruby"&gt;
respond_with(@product, :responder =&amp;gt; MyResponder)
&lt;/pre&gt;

&lt;p&gt;Wenn man wissen m&amp;ouml;chte, wie eine &lt;a href="http://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/responder.rb"&gt;Responder-Klasse&lt;/a&gt; erstellte wird, sollte man sich die in Rails 3 eingebaute Responder-Klasse anschauen. Der Code ist recht einfach zu lesen und gut dokumentiert und man bekommt eine bessere Vorstellung davon, wie der Responder funktioniert.&lt;/p&gt;

&lt;p&gt;Das ist alles f&amp;uuml;r diese Episode. Wie man gesehen hat, ist &lt;code&gt;respond_with&lt;/code&gt; eine wirklich zweckm&amp;auml;&amp;szlig;ige Herangehensweise, viele Formate zu bew&amp;auml;ltigen. Sollte man aber feststellen, dass man es zu stark anpasst, ist es wahrscheinlich einfacher, respond_with nicht zu verwenden oder eine eigene Responder-Klasse zu schreiben.&lt;/p&gt;</description>
      <pubDate>Tue, 07 Sep 2010 19:05:26 +0000</pubDate>
      <guid>http://de.asciicasts.com/episodes/224-controller-in-rails-3</guid>
      <link>http://de.asciicasts.com/episodes/224-controller-in-rails-3</link>
    </item>
    <item>
      <title>Unobtrusive JavaScript</title>
      <description>&lt;p&gt;In unserer Serie &amp;uuml;ber die neuen Features von Rails 3 betrachten wir in dieser Episode das Thema &lt;em&gt;dezentes bzw. unaufdringliches JavaScript&lt;/em&gt; (unobtrusive Javascript). Dezentes JavaScript bedeutet, JavaScript- und HTML-Code weitestgehend zu trennen. Im ausgelieferten HTML-Dokument sollten also nach M&amp;ouml;glichkeit keine oder so gut wie keine JavaScript-Anweisungen stehen, sondern nur in externen Dateien. Dies funktioniert analog wie die Trennung von Struktur (HTML) und Design (CSS). Bevor wir zur eigentlichen Anwendung in Rails kommen, hier ein kleines Beispiel anhand eines einfachen HTML-Dokuments.&lt;/p&gt;

&lt;p&gt;Der nachfolgende Screenshot zeit eine Webseite mit einem Link darauf. Sobald der Link aufgerufen wird, wird ein JavaScript &lt;code&gt;alert&lt;/code&gt; ausgef&amp;uuml;hrt, der &amp;ldquo;Hello world!&amp;rdquo; ausgibt.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/343/original/E205I01.png" width="639" height="337" alt="The alert shown by the inline JavaScript."/&gt;
&lt;/div&gt;

&lt;p&gt;Der HTML-Code f&amp;uuml;r diese Seite sieht so aus::&lt;/p&gt;

&lt;pre class="ruby"&gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;UJS Example&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;alert(&amp;#x27;Hello world!&amp;#x27;); return false;&amp;quot;&amp;gt;Click Here&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;In dieser Seite haben wir direkt im HTML-Dokument im &lt;code&gt;onclick&lt;/code&gt;-Attribut JavaScript-Code stehen. Solche Anweisungen sind also keineswegs dezent/unaufdringlich (unobtrusive eben), was nicht gerade ideal ist, da wir Verhalten und Inhalt miteinander vermischen. In den 90er Jahren wurden Webseiten sehr h&amp;auml;ufig mit &lt;code&gt;&amp;lt;font&amp;gt;&lt;/code&gt;-Tags gestaltet, um Schriftart und -aussehen von Texten einzustellen, da es damals noch kein CSS gab. Daraus resultierte automatisch, dass man, wenn man beispielsweise die Gr&amp;ouml;&amp;szlig;e aller mit &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt; deklarierten Abs&amp;auml;tze ver&amp;auml;ndern wollte, nicht selten hunderte &amp;uuml;ber mehrere Dateien verteilte &amp;Auml;nderungen durchf&amp;uuml;hren musste. Als die Browser endlich anfingen, CSS zu unterst&amp;uuml;tzen, konnte man das Styling der Seite in Stylesheets auslagern und nur noch die Struktur und den Inhalt der Seite im HTML belassen. So wurde es deutlich einfacher, das Aussehen einer Webseite einheitlich anzupassen.&lt;/p&gt;

&lt;p&gt;Dasselbe gilt f&amp;uuml;r JavaScript: Viele kleine Codeschnipsel innerhalb des HTML-Dokuments, meistens in Attributen wie &lt;code&gt;onclick&lt;/code&gt;, vermischt verschiedene Zust&amp;auml;ndigkeiten und erschwert die Wartung nicht unerheblich. Das Herausl&amp;ouml;sen von JavaScript in eigenst&amp;auml;ndige Dateien, die im &lt;code&gt;head&lt;/code&gt;-Bereich von HTML-Dokumenten eingebunden werden, vermeidet Code-Duplikate, erm&amp;ouml;glicht einfache Refactorings und erleichtert die Erstellung von und die Fehlersuche in komplexen Webanwendungen.&lt;/p&gt;

&lt;p&gt;Nur wie machen wir den JavaScript-Code in unserem einfachen Beispiel unaufdringlich? Der zentrale Schritt ist das Verschieben des Codes aus dem &lt;code&gt;onclick&lt;/code&gt;-Attribut in eine eigene Datei und die Verwendung eines JavaScript-Frameworks, hier &lt;em&gt;jQuery&lt;/em&gt;, um die Anweisungen mit den richtigen HTML-Elementen zu verbinden. Zeigen wir zuerst die umgewandelte Datei und beleuchten dann die durchgef&amp;uuml;hrten &amp;Auml;nderungen.&lt;/p&gt;

&lt;pre class="ruby"&gt;
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;UJS Example&amp;lt;/title&amp;gt;
    &amp;lt;script src=&amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&amp;quot; type=&amp;quot;text/javascript&amp;quot; charset=&amp;quot;UTF-8&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;script type=&amp;quot;text/javascript&amp;quot;charset=&amp;quot;UTF-8&amp;quot;&amp;gt;
      $(function () {
        $(&amp;#x27;#alert&amp;#x27;).click(function () {
          alert(&amp;#x27;Hello, world!&amp;#x27;);
          return false;
        })
      });
    &amp;lt;/script&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;alert&amp;quot;&amp;gt;Click Here&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Zuallererst f&amp;auml;llt auf, dass wir die Anweisungen &lt;strong&gt;doch nicht&lt;/strong&gt; in eine eigene Datei verschoben haben. Dies dient hier nur der besseren &amp;Uuml;bersicht, da sich die &amp;Auml;nderungen so leichter darstellen lassen.&lt;/p&gt;

&lt;p&gt;Das &lt;code&gt;a&lt;/code&gt;-Element wurde um sein &lt;code&gt;onclick&lt;/code&gt;-Attribut erleichtert und hat stattdessen ein &lt;code&gt;id&lt;/code&gt;-Attribut dazubekommen, damit wir dieses Element leicht vom jQuery-Code aus adressieren k&amp;ouml;nnen. Weiterhin haben wir im &lt;code&gt;head&lt;/code&gt;-Bereich der Seite die jQuery-Bibliothek eingebunden und darunter die eigentlichen Anweisungen (die selbstverst&amp;auml;ndlich in einer eigenen Datei stehen sollten und auch mit Hilfe eines &lt;code&gt;script&lt;/code&gt;-Tags eingebunden werden sollten). Das Skript beginnt mit dem Aufruf der &lt;code&gt;$&lt;/code&gt;-Methode von jQuery, der eine anonyme Funktion als Parameter &amp;uuml;bergeben wird. Diese Funktion wird ausgef&amp;uuml;hrt, sobald das &lt;em&gt;DOM&lt;/em&gt; der Seite geladen wird und enth&amp;auml;lt die jQuery-Anweisungen, die anhand der &lt;code&gt;id&lt;/code&gt; das &lt;code&gt;a&lt;/code&gt;-Element finden und eine Funktion an dessen &lt;code&gt;click&lt;/code&gt;-Event anh&amp;auml;ngen. Diese Funktion wiederum f&amp;uuml;hrt den eigentlichen &lt;code&gt;alert&lt;/code&gt;-Aufruf durch und gibt &lt;code&gt;false&lt;/code&gt; zur&amp;uuml;ck, damit der Browser dem Link nicht folgt.&lt;/p&gt;

&lt;p&gt;Wenn wir die Seite neu laden, verh&amp;auml;lt sie sich immer noch genau so wie zuvor: Der &lt;code&gt;alert&lt;/code&gt; wird angezeigt, sobald der Link angeklickt wird.&lt;/p&gt;

&lt;p&gt;Auf den ersten Blick dr&amp;auml;ngt sich der Eindruck auf, dass man hierf&amp;uuml;r unverh&amp;auml;ltnism&amp;auml;ssig viel Arbeit investieren muss, um die Trennung durchzuf&amp;uuml;hren, doch dieses simple Beispiel demonstriert schlicht und ergreifend auch nicht die wirklichen Vorteile, die sich mit dezentem JavaScript ergeben. Immerhin haben wir &lt;strong&gt;eine&lt;/strong&gt; Zeile JavaScript-Code genommen und &lt;strong&gt;sechs&lt;/strong&gt; daraus gemacht. Wie gesagt ist dieses Beispiel auch nicht daf&amp;uuml;r geeignet, um die Vorteile aufzuzeigen, sondern dient lediglich der Demonstration, wie die Technik angewendet wird und wo sich Unterschiede ergeben. Die Vorz&amp;uuml;ge von unaufdringlichem Code werden erst wirklich deutlich, wenn eine Anwendung viel mehr und komplexeres JavaScript einsetzt, da sich Code-Duplikate viel leichter identifizieren und beheben lassen, wenn man den gesamten Code an einer Stelle hat, anstatt &amp;uuml;berall in der Anwendung nach einzelnen Fragmenten suchen zu m&amp;uuml;ssen.&lt;/p&gt;

&lt;p&gt;Ein gro&amp;szlig;es Problem mit dieser Technik ist allerdings, dass der Code gew&amp;ouml;hnlich in einer statischen JavaScript-Datei gespeichert ist. Wie kann man also dynamischen, serverseitigen Inhalt in das Skript einf&amp;uuml;gen, wo es ja nicht mehr inline im eigentlichen &lt;em&gt;View&lt;/em&gt;-Code steht?&lt;/p&gt;

&lt;p&gt;In HTML 5 kann man so genannte &lt;em&gt;custom data attributes&lt;/em&gt; verwenden, um zu einem bestimmten Element geh&amp;ouml;rige Daten in der Seite speichern kann. Diese Attribute sind genau wie alle anderen HTML-Attribute, nur ihr Name beginnt immer mit &lt;code&gt;data-&lt;/code&gt;. Um beispielsweise die Nachricht, die angezeigt werden soll, wenn der Link angeklickt wird, von der Rails-Applikation aus dynamisch festzulegen, schreiben wir unseren Code um:&lt;/p&gt;

&lt;pre class="ruby"&gt;
&amp;lt;a href=&amp;quot;#&amp;quot; id=&amp;quot;alert&amp;quot; data-message=&amp;quot;Hello from UJS&amp;quot;&amp;gt;Click Here&amp;lt;/a&amp;gt;
&lt;/pre&gt;
&lt;p&gt;In the JavaScript we can then alter the alert to show the text from our new attribute:&lt;/p&gt;
&lt;pre class="javascript"&gt;
$(function () {
  $(&amp;#x27;#alert&amp;#x27;).click(function () {
    alert(this.getAttribute(&amp;#x27;data-message&amp;#x27;));
    return false;
   })
});
&lt;/pre&gt;

&lt;p&gt;Nach dem Neuladen der Seite sehen wir die Nachricht aus dem &lt;code&gt;data-&lt;/code&gt;Attribut.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/344/original/E205I02.png" width="747" height="440" alt="The alert created by unobtrusive JavaScript."/&gt;
&lt;/div&gt;

&lt;h3&gt;Wie Rails 3 &lt;code&gt;data&lt;/code&gt;-Attribute verwendet&lt;/h3&gt;

&lt;p&gt;Rails 3 nutzt diese &lt;em&gt;custom data attributes&lt;/em&gt; bei der Umsetzung von unaufdringlichem JavaScript-Code, indem Daten an JavaScript &amp;uuml;bergeben werden k&amp;ouml;nnen. Betrachten wir nun, wie sich das in einer Rails-Anwendung einsetzen l&amp;auml;sst. Unser Beispiel ist eine einfache eCommerce-Anwendung, die eine Liste von Produkten hat, die durchsucht werden kann. Dar&amp;uuml;ber hinaus gibt es noch Links zum Bearbeiten und L&amp;ouml;schen von Produkten. Die L&amp;ouml;schen-Links scheinen nicht mehr richtig zu funktionieren:&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/345/original/E205I03.png" width="800" height="357" alt="The product page with the non-working destroy link."/&gt;
&lt;/div&gt;

&lt;p&gt;Dies ist ein typisches Problem mit Rails 3 Anwendungen. Wenn Sie gerade eine neue Applikation aufsetzen oder von einer fr&amp;uuml;heren Version von Rails portieren, werden Sie feststellen, dass manche Stellen der Anwendung, an denen JavaScript verwendet wird, nicht mehr funktionieren!&lt;/p&gt;

&lt;p&gt;Der &lt;code&gt;view&lt;/code&gt;-Code der den &amp;ldquo;Destroy&amp;rdquo;-Link erzeugt ist ein normaler &lt;code&gt;link_to_method&lt;/code&gt;-Aufruf mit einer &lt;code&gt;:confirm&lt;/code&gt;-Option, die einen JavaScript-&lt;code&gt;confirm&lt;/code&gt;-Dialog anzeigt und mit einer &lt;code&gt;:method&lt;/code&gt;-Option, die auf &lt;code&gt;:delete&lt;/code&gt; gesetzt ist, damit der Request nicht als einfacher &lt;em&gt;GET&lt;/em&gt;-Request abgesetzt wird, sondern mit dem &lt;em&gt;DELETE&lt;/em&gt;-Verb.&lt;/p&gt;


&lt;p class="codeFilePath"&gt;/app/views/products/show.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= link_to &amp;quot;Destroy&amp;quot;, @product, :confirm =&amp;gt; &amp;quot;Are you sure?&amp;quot;, :method =&amp;gt; :delete %&amp;gt;
&lt;/pre&gt;
&lt;p&gt;What&amp;rsquo;s interesting here is the HTML source that this code generates:&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;a href=&amp;quot;/products/8&amp;quot; data-confirm=&amp;quot;Are you sure?&amp;quot; data-method=&amp;quot;delete&amp;quot; rel=&amp;quot;nofollow&amp;quot;&amp;gt;Destroy&amp;lt;/a&amp;gt;
&lt;/pre&gt;

&lt;p&gt;In Rails 2 wurde durch jeden &lt;code&gt;link_to&lt;/code&gt;-Aufruf, der als Resultat einen Link auf einen &lt;em&gt;POST&lt;/em&gt;-, &lt;em&gt;DELETE&lt;/em&gt;- oder &lt;em&gt;PUT&lt;/em&gt;Request haben sollte, jede Menge inline-JavaScript-Code erzeugt, der den &lt;code&gt;confirm&lt;/code&gt;-Dialog ausl&amp;ouml;ste und den entsprechenden Request durchf&amp;uuml;hren sollte. Im Vergleich dazu ist der von Rails 3 ausgelieferte HTML-Code erheblich &amp;uuml;bersichtlicher und durch die Nutzung von HTML 5 lassen sich auch mehrere Attribute erzeugen, beispielsweise ein &lt;code&gt;data-confirm&lt;/code&gt;-Attribut, das die Best&amp;auml;tigungsnachricht enth&amp;auml;lt und ein weiteres &lt;code&gt;data-method&lt;/code&gt;, das die eigentliche Methode beinhaltet.&lt;/p&gt;

&lt;p&gt;Der Grund, warum die Links nicht funktionieren ist, dass bisher die ben&amp;ouml;tigten JavaScript-Dateien im &lt;code&gt;head&lt;/code&gt;-Bereich der Seite geladen werden und der Link daher einen normalen &lt;em&gt;GET&lt;/em&gt;-Request ausl&amp;ouml;st, da kein JavaScript das &lt;code&gt;click&lt;/code&gt;-Event ver&amp;auml;ndert hat.&lt;/p&gt;

&lt;p&gt;Um dieses Problem zu l&amp;ouml;sen, f&amp;uuml;gt man einfach eine weitere Zeile in den &lt;code&gt;head&lt;/code&gt;-Bereich ein:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= javascript_include_tag :defaults %&amp;gt;
&amp;lt;%= csrf_meta_tag %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Die erste Zeile sollte bekannt sein. Sie veranlasst, dass die Standard-JavaScript-Dateien f&amp;uuml;r Rails-Anwendungen geladen werden. Die Zweite jedoch erzeugt zwei &lt;code&gt;meta&lt;/code&gt;-Tags, die das &lt;em&gt;authenticity-Token&lt;/em&gt; enthalten, die n&amp;ouml;tig sind, um &lt;em&gt;DELETE&lt;/em&gt;-Requests durchf&amp;uuml;hren zu k&amp;ouml;nnen. Laden wir also die Seite neu und betrachten wir den ausgelieferten HTML-Code, um die Ausgaben dieser beiden Zeilen zu sehen:&lt;/p&gt;

&lt;pre class="ruby"&gt;
&amp;lt;script src=&amp;quot;/javascripts/prototype.js?1268677667&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;/javascripts/effects.js?1268677667&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;/javascripts/dragdrop.js?1268677667&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;/javascripts/controls.js?1268677667&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;/javascripts/rails.js?1268677667&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&amp;quot;/javascripts/application.js?1268677667&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;meta name=&amp;quot;csrf-param&amp;quot; content=&amp;quot;authenticity_token&amp;quot;/&amp;gt;
&amp;lt;meta name=&amp;quot;csrf-token&amp;quot; content=&amp;quot;9ImdFvbeW7ih9oKqBDQ3O889q/hJ1q5uajpT4DFDAoA=&amp;quot;/&amp;gt;
&lt;/pre&gt;

&lt;p&gt;In der Seite laden wir jetzt also alle JavaScript-Dateien, die unsere Applikation braucht und haben zus&amp;auml;tzlich zwei &lt;code&gt;meta&lt;/code&gt;-Tags, die n&amp;ouml;tig sind, um &lt;em&gt;cross-site request forgery&lt;/em&gt; zu unterbinden. Dies versichert, dass &lt;em&gt;PUT&lt;/em&gt;- und &lt;em&gt;DELETE&lt;/em&gt;-Requests tats&amp;auml;chlich vom richtigen Benutzer kommen und nicht einer anderen Seite oder von einem Hacker.&lt;/p&gt;

&lt;p&gt;Sobald diese Vorbedingungen erf&amp;uuml;llt sind, sollte der Link endlich wie erwartet funktionieren:&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/346/original/E205I04.png" width="802" height="360" alt="The destroy link now works."/&gt;
&lt;/div&gt;

&lt;h3&gt;Hinzuf&amp;uuml;gen von &lt;em&gt;AJAX&lt;/em&gt;-Funktionalit&amp;auml;t zum Suchfeld&lt;/h3&gt;

&lt;p&gt;Als N&amp;auml;chstes ver&amp;auml;ndern wir das Suchformular auf der &lt;code&gt;index&lt;/code&gt;-Seite so, dass es beim Abschicken einen &lt;em&gt;AJAX&lt;/em&gt;-Aufruf verwendet anstelle des bisher verwendeten &lt;em&gt;GET&lt;/em&gt;-Requests. Der Code f&amp;uuml;r das &lt;code&gt;index&lt;/code&gt;-View lautet:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/products/index.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% title &amp;quot;Products&amp;quot; %&amp;gt;

&amp;lt;% form_tag products_path, :method =&amp;gt; :get do %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= text_field_tag :search, params[:search] %&amp;gt;
    &amp;lt;%= submit_tag &amp;quot;Search&amp;quot;, :name =&amp;gt; nil %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;

&amp;lt;div id=&amp;quot;products&amp;quot;&amp;gt;
  &amp;lt;%= render @products %&amp;gt;
&amp;lt;/div&amp;gt;

&amp;lt;p&amp;gt;&amp;lt;%= link_to &amp;quot;New Product&amp;quot;, new_product_path %&amp;gt;&amp;lt;/p&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Das Formular, das hier verwendet wird, nutzt die Technik, die in &lt;a href="http://railscasts.com/episodes/37-simple-search-form"&gt;Episode 37&lt;/a&gt; vorgestellt wurde. In fr&amp;uuml;heren Versionen von Rails musste man, um &lt;em&gt;AJAX&lt;/em&gt;-Funktionalit&amp;auml;t zu erreichen, den &lt;code&gt;form_tag&lt;/code&gt; durch einen &lt;code&gt;form_remote_tag&lt;/code&gt; ersetzen. Diese Methode generiert allerdings sehr viel inline-JavaScript, was wir jetzt ja gerade vermeiden wollen.&lt;/p&gt;

&lt;p&gt;Viele der &lt;code&gt;remote&lt;/code&gt;-Hilfsfunktionen ist nicht mehr verf&amp;uuml;gbar in Rails 3. Um sie wieder freizuschalten, k&amp;ouml;nnte man das &lt;a href="http://github.com/rails/prototype_legacy_helper"&gt;Prototype Legacy Helper&lt;/a&gt; Plugin installieren, doch wir gehen hier den neuen Rails-3-Weg.&lt;/p&gt;

&lt;p&gt;Als Alternative zum &lt;code&gt;form_remote_tag&lt;/code&gt; bleiben wir beim &lt;code&gt;form_tag&lt;/code&gt; und f&amp;uuml;gen einen neuen Parameter &lt;code&gt;:remote&lt;/code&gt; hinzu.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/products/index.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% form_tag products_path, :method =&amp;gt; :get, :remote =&amp;gt; true do %&amp;gt;
  &amp;lt;p&amp;gt;
    &amp;lt;%= text_field_tag :search, params[:search] %&amp;gt;
    &amp;lt;%= submit_tag &amp;quot;Search&amp;quot;, :name =&amp;gt; nil %&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Dieser neue Parameter kann auch mit anderen Hilfsfunktionen wie &lt;code&gt;link_to&lt;/code&gt;, &lt;code&gt;button_to&lt;/code&gt; und &lt;code&gt;form_for&lt;/code&gt; verwendet werden. Laden wir die Seite neu und betrachten, wie der neue Formular-Code funktioniert:&lt;/p&gt;

&lt;pre class="ruby"&gt;
&amp;lt;form action=&amp;quot;/products&amp;quot; data-remote=&amp;quot;true&amp;quot; method=&amp;quot;get&amp;quot;&amp;gt;  &amp;lt;p&amp;gt;
    &amp;lt;input id=&amp;quot;search&amp;quot; name=&amp;quot;search&amp;quot; type=&amp;quot;text&amp;quot; /&amp;gt;
    &amp;lt;input type=&amp;quot;submit&amp;quot; value=&amp;quot;Search&amp;quot; /&amp;gt;
  &amp;lt;/p&amp;gt;
&amp;lt;/form&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Das Formular-Element ist dasselbe wie zuvor, hat aber ein neues &lt;code&gt;data-remote&lt;/code&gt;-Attribut. Es gibt kein inline-JavaScript, da das neue Attribut allein schon genug ist, um mit Hilfe des Codes in &lt;em&gt;rails.js&lt;/em&gt; einen &lt;em&gt;AJAX&lt;/em&gt;- anstelle eines &lt;em&gt;GET&lt;/em&gt;-Requests auszul&amp;ouml;sen.&lt;/p&gt;

&lt;p&gt;Als N&amp;auml;chstes m&amp;uuml;ssen wir noch den Code schreiben, der die Antwort des &lt;em&gt;AJAX&lt;/em&gt;-Aufrufs verarbeiten kann. Die Liste mit den Produkten ist in einem &lt;code&gt;div&lt;/code&gt;-Container mit der ID &lt;code&gt;products&lt;/code&gt;, also m&amp;uuml;ssen wir einfach den Inhalt dieses &lt;code&gt;div&lt;/code&gt;-Elements aktualisieren, um die angeforderten Suchergebnisse anzuzeigen. Das Formular wird zur &lt;code&gt;index&lt;/code&gt;-Aktion des &lt;code&gt;ProductController&lt;/code&gt;s abgeschickt, also m&amp;uuml;ssen wir einfach ein neues &lt;em&gt;view&lt;/em&gt;-Template &lt;em&gt;index.js.erb&lt;/em&gt; erzeugen, das JavaScript-Anfragen beantworten kann.&lt;/p&gt;

&lt;p&gt;Wir k&amp;ouml;nnen in dieser Datei beliebigen JavaScript-Code schreiben, der ausgef&amp;uuml;hrt wird, sobald er beim Browser angekommen ist. Der Code zum Aktualisieren des Inhalts des &lt;code&gt;products&lt;/code&gt;-Containers sieht beispielsweise so aus:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/products/index.js.erb&lt;/p&gt;
&lt;pre class="javascript"&gt;
$(&amp;quot;products&amp;quot;).update(&amp;quot;&amp;lt;%= escape_javascript(render(@products))%&amp;gt;&amp;quot;);
&lt;/pre&gt;
&lt;p&gt;When we reload the page and submit the form the search will be made with an AJAX call and we can see this as the page&amp;rsquo;s URL doesn&amp;rsquo;t change when the search is made.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/347/original/E205I05.png" width="801" height="409" alt="The search form working with AJAX."/&gt;
&lt;/div&gt;

&lt;p&gt;Also kann man in Rails 3 sehr einfach unaufdringlichen JavaScript-Code f&amp;uuml;r &lt;em&gt;AJAX&lt;/em&gt;-Aufrufe schreiben, indem man den &lt;code&gt;:remote&lt;/code&gt;-Parameter verwendet und ein JavaScript-Template f&amp;uuml;r die entsprechende Aktion festlegt.&lt;/p&gt;

&lt;h3&gt;Auswechseln des Frameworks&lt;/h3&gt;

&lt;p&gt;Zu guter letzt demonstrieren wir noch, wie man die verwendeten JavaScript-Frameworks, die in unserer Applikation verwendet werden, gegen andere austauschen kann. Unsere Applikation verwendet momentan &lt;em&gt;Prototype&lt;/em&gt;, das standardm&amp;auml;ssig bei Rails dabei ist, doch was, wenn wir stattdessen &lt;em&gt;jQuery&lt;/em&gt; verwenden m&amp;ouml;chten?&lt;/p&gt;

&lt;p&gt;Zuerst m&amp;uuml;ssen wir die Einbindung im Hauptlayout&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= javascript_include_tag :defaults %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;mit der folgenden Anweisung ersetzen:&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/layouts/application.html.erb&lt;/p&gt;
&lt;pre class="ruby"&gt;
&amp;lt;%= javascript_include_tag &amp;quot;http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&amp;quot;, &amp;quot;jquery.rails.js&amp;quot; %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Die erste Datei in er Liste ist die neueste jQuery-Version frisch vom Google-Server. Das alleine gen&amp;uuml;gt allerdings noch nicht, da wir ein &amp;Auml;quivalent zur &lt;em&gt;rails.js&lt;/em&gt;-Datei ben&amp;ouml;tigen, die wir schon zuvor verwendet haben, um das Rails-spezifische JavaScript zu verarbeiten. Auf Github gibt es das offizielle &lt;a href="http://github.com/rails/jquery-ujs"&gt;jquery-ujs Projekt&lt;/a&gt;. Es beinhaltet eine &lt;em&gt;rails.js&lt;/em&gt;-Datei, die heruntergeladen werden und in unseren Projekten verwendet werden kann. Wir haben die Datei heruntergeladen und im Ordner &lt;em&gt;/public/javascripts&lt;/em&gt; abgelegt und es in &lt;em&gt;jquery.rails.js&lt;/em&gt; umbenannt.&lt;/p&gt;

&lt;p&gt;Jetzt m&amp;uuml;ssen wir noch s&amp;auml;mtliche Skripte, die in unserer Anwendung vorkommen, von &lt;em&gt;Prototype&lt;/em&gt; auf &lt;em&gt;jQuery&lt;/em&gt; umschreiben, da sich die Syntax der beiden Frameworks unterscheidet. Dies bringt also ein paar &amp;Auml;nderungen in &lt;em&gt;index.js.erb&lt;/em&gt; mit sich, beispielsweise &lt;code&gt;#products&lt;/code&gt; als Selektor f&amp;uuml;r das &lt;code&gt;div&lt;/code&gt;-Element anstelle von &lt;code&gt;products&lt;/code&gt; oder das Austauschen der &lt;code&gt;update&lt;/code&gt;-Methode von &lt;em&gt;Prototype&lt;/em&gt; durch die &lt;em&gt;jQuery&lt;/em&gt;-Methode &lt;code&gt;html&lt;/code&gt;.&lt;/p&gt;

&lt;p class="codeFilePath"&gt;/app/views/products/index.js.erb&lt;/p&gt;
&lt;pre class="javascript"&gt;
$(&amp;quot;#products&amp;quot;).html(&amp;quot;&amp;lt;%= escape_javascript(render(@products))%&amp;gt;&amp;quot;);
&lt;/pre&gt;

&lt;p&gt;Unsere Anwendung wird sich jetz exakt so verhalten wie zuvor, nur dass unter der Motorhaube jQuery anstatt Prototype verwendet wird.&lt;/p&gt;

&lt;h3&gt;Stilles Zur&amp;uuml;ckfallen auf nicht-JavaScript-Funktionalit&amp;auml;t&lt;/h3&gt;

&lt;p&gt;Wenn ein Benutzer unsere Anwendung verwenden m&amp;ouml;chte, dessen Browser kein JavaScript aktiviert hat, wird sich das Suchformular wie gehabt verhalten und beim Abschicken einen normalen &lt;em&gt;GET&lt;/em&gt;-Aufruf ausf&amp;uuml;hren. L&amp;ouml;schen von Produkten wird jedoch nicht funktionieren. Dies ist ein gel&amp;auml;ufiges Problem, da Rails JavaScript nutzt, um &lt;em&gt;DELETE&lt;/em&gt; oder &lt;em&gt;PUT&lt;/em&gt; zu simulieren, weil HTML-Links keine anderen als &lt;em&gt;GET&lt;/em&gt;-Requests ausl&amp;ouml;sen k&amp;ouml;nnen. Eine m&amp;ouml;gliche L&amp;ouml;sung ist, den Link mit einem Button zu ersetzen, indem man &lt;code&gt;button_to&lt;/code&gt; verwendet. Dummerweise k&amp;ouml;nnen Buttons nur schwer in das Layout der Seite eingef&amp;uuml;gt werden, weswegen in den meisten F&amp;auml;llen nur ein Link in Frage kommt. Eine weitere Technik wurde bereits in &lt;a href="http://railscasts.com/episodes/77-destroy-without-javascript"&gt;Episode 77&lt;/a&gt; gezeigt, wobei eine eigene Best&amp;auml;tigungs-Seite gezeigt wird, bevor die eigentliche L&amp;ouml;schung vorgenommen wird.&lt;/p&gt;
</description>
      <pubDate>Tue, 30 Mar 2010 17:41:09 +0000</pubDate>
      <guid>http://de.asciicasts.com/episodes/205-unobtrusive-javascript</guid>
      <link>http://de.asciicasts.com/episodes/205-unobtrusive-javascript</link>
    </item>
    <item>
      <title>Active Record Queries in Rails 3</title>
      <description>&lt;p&gt;Im Verlauf der letzten beiden Episoden haben wir Ihnen gezeigt, wie Sie Ihren Computer f&amp;uuml;r Rails 3 vorbereiten und eine neue Rails 3 Applikation erzeugen k&amp;ouml;nnen. In dieser Folge werden wir einige der neuen Features betrachten. Wir beginnen mit ActiveRecord, der jetzt ein neues Interface anbietet, um Datenbankanfragen durchzuf&amp;uuml;hren. Pratik Naik hat sich diesem Thema k&amp;uuml;rzlich &lt;a href="http://m.onkey.org/2010/1/22/active-record-query-interface"&gt;in einem Beitrag in seinem Blog&lt;/a&gt; ausf&amp;uuml;hrlich gewidmet, der durchaus einen Blick wert ist.&lt;/p&gt;
  
&lt;h3&gt;Ein paar einfache Beispiele&lt;/h3&gt;

&lt;p&gt;Zu Beginn zeigen wir Ihnen ein paar Beispiele von alten ActiveRecord-&lt;code&gt;find&lt;/code&gt; Aufrufen und &amp;uuml;bersetzen diese in das neue Format. Zu diesem Zweck verwenden wir eine einfache Rails Applikation mit zwei Models: &lt;code&gt;Article&lt;/code&gt; und &lt;code&gt;Comment&lt;/code&gt;, wobei gilt: &lt;b&gt;&lt;code&gt;Article:&lt;/code&gt;&lt;/b&gt; &lt;code&gt;has_many :comments&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Der erste &lt;code&gt;find&lt;/code&gt;-Aufruf gibt die zehn zuletzt ver&amp;ouml;ffentlichen Artikel zur&amp;uuml;ck:&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.find(:all, :order =&amp;gt; &amp;quot;published_at desc&amp;quot;, :limit =&amp;gt; 10)
&lt;/pre&gt;

&lt;p&gt;Grundlegend sieht man sich beim &amp;uuml;bersetzen von ActiveRecord Queries in das neue Rails 3 Format den Hash mit Optionen an, die an &lt;code&gt;find&lt;/code&gt; &amp;uuml;bergeben werden und ersetzt jeweils einen Teil mit einem &amp;auml;quivalenten Methodenaufruf. An Stelle des &lt;code&gt;find&lt;/code&gt;-Aufrufs von oben kann man schreiben:&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.order(&amp;quot;published_at desc&amp;quot;).limit(10)
&lt;/pre&gt;

&lt;p&gt;Wie Sie sehen, ist die &amp;Uuml;bersetzung sehr einfach und bietet eine insgesamt sch&amp;ouml;nere Syntax.&lt;/p&gt;

&lt;p&gt;Die Optionen aus dem alten Hash lassen sich direkt in die neuen Methoden &amp;uuml;bertragen, wie das n&amp;auml;chste Beispiel zeigt.&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.find(:all, :conditions =&amp;gt; [&amp;quot;published_at &amp;lt;= ?&amp;quot;, Time.now], :include =&amp;gt; :comments)
&lt;/pre&gt;

&lt;p&gt;Es gibt nur zwei tats&amp;auml;chliche Ausnahmen, die im nachfolgenden Beispiel verwendet wurden. Der soeben genannte &lt;code&gt;find&lt;/code&gt;-Aufruf liefert alle Artikel, deren Ver&amp;ouml;ffentlichungszeitpunkt in der Vergangenheit liegt inklusive der dazugeh&amp;ouml;rigen Kommentare. In Rails 3 wird daraus:&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.where(&amp;quot;published_at &amp;lt;= ?&amp;quot;, Time.now).includes(:comments)
&lt;/pre&gt;

&lt;p&gt;An Stelle von &lt;code&gt;:conditions&lt;/code&gt; k&amp;ouml;nnen wir jetzt die &lt;code&gt;where&lt;/code&gt;-Methode verwenden, der wir dieselben Argumente &amp;uuml;bergeben. Sie k&amp;ouml;nnen als Array oder einzeln &amp;uuml;bergeben werden. Um assoziierte Eintr&amp;auml;ge zu bekommen, verwendet man anstatt &lt;code&gt;:include&lt;/code&gt; jetzt die (um ein &lt;em&gt;s&lt;/em&gt; erweiterte) &lt;code&gt;includes&lt;/code&gt;-Methode. Alle anderen Optionen, die wir bisher an &lt;code&gt;find&lt;/code&gt; &amp;uuml;bergeben haben, wurden zu Methoden mit den gleichen Namen wie die jeweilige Option selbst.&lt;/p&gt;
 
&lt;p&gt;Unser letztes Beispiel sucht den neuesten Artikel.&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.find(:first, :order =&amp;gt; &amp;quot;published_at desc&amp;quot;)
&lt;/pre&gt;

&lt;p&gt;Unter Verwendung der neuen Rails 3 Syntax wird daraus:&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.order(&amp;quot;published_at desc&amp;quot;).first()
&lt;/pre&gt;

&lt;p&gt;Beachtenswert ist hier, dass wir &lt;code&gt;first&lt;/code&gt; erst am Ende der Methodenverkettung aufrufen.&lt;/p&gt;

&lt;p&gt;Da wir in absteigender Reihenfolge suchen, k&amp;ouml;nnten wir die Anweisung auch &amp;auml;quivalent umwandeln zu:&lt;/p&gt;

&lt;pre class="ruby"&gt;
Article.order(&amp;quot;published_at&amp;quot;).last()
&lt;/pre&gt;

&lt;p&gt;Das Ergebnis w&amp;auml;re die gleiche Datenbankanfrage, doch mit knapperem Code.&lt;/p&gt;

&lt;p&gt;In Rails 3 k&amp;ouml;nnen wir entweder die alten &lt;code&gt;find&lt;/code&gt;-Methoden oder die neuen Rails 3 Methoden. In Rails 3.1 jedoch werden die alten Methoden als veraltet markiert und mit Rails Version 3.2 werden sie vollends entfernt werden. Es ist daher notwendig, alle &lt;code&gt;find&lt;/code&gt;s in Ihren Applikationen auf die neue Syntax zu migrieren, damit sie mit zuk&amp;uuml;nftigen Versionen von Rails 3 kompatibel sein werden.&lt;/p&gt;

&lt;p&gt;An dieser Stelle werden Sie sich vielleicht fragen, was genau der Grund f&amp;uuml;r diese neue Syntax ist - vor Allem, weil mit ihrer Einf&amp;uuml;hrung sehr viele existierende Rails-Applikationen nicht mehr funktionieren werden, wenn die Umstellung stattfindet. Der Grund f&amp;uuml;r diese drastische Neuerung liegt beim m&amp;auml;chtigen &lt;em&gt;lazy loading&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;Lazy Loading&lt;/h3&gt;

&lt;p&gt;Um lazy loading zu demonstrieren, verwenden wie die Konsole unserer Applikation. Wenn wir alle Artikel abfragen, bekommen wir wie erwartet ein Array mit allen Artikeln. Im Beispiel haben wir drei Artikel in unserer Datenbank.&lt;/p&gt;

&lt;pre class="terminal"&gt;
ruby-1.9.1-p378 &amp;gt; Article.all =&amp;gt; [#&amp;lt;Article id: 1, name: &amp;quot;It&amp;#x27;s Ancient&amp;quot;, published_at: nil, hidden: false, 
created_at: &amp;quot;2010-02-22 20:35:42&amp;quot;, updated_at: &amp;quot;2010-02-22 20:35:42&amp;quot;&amp;gt;, 
#&amp;lt;Article id: 2, name: &amp;quot;Can&amp;#x27;t See Me&amp;quot;, published_at: nil, hidden: false, 
created_at: &amp;quot;2010-02-22 20:37:03&amp;quot;, updated_at: &amp;quot;2010-02-22 20:37:03&amp;quot;&amp;gt;, 
#&amp;lt;Article id: 3, name: &amp;quot;To the Future!&amp;quot;, published_at: nil, hidden: false, 
created_at: &amp;quot;2010-02-22 20:38:17&amp;quot;, updated_at: &amp;quot;2010-02-22 20:38:17&amp;quot;&amp;gt;]
&lt;/pre&gt; 

&lt;p&gt;Wenn wir alle Artikel alphabetisch sortiert wollen, verwenden wir die &lt;code&gt;order&lt;/code&gt;-Methode:&lt;/p&gt;

&lt;pre class="terminal"&gt;
ruby-1.9.1-p378 &amp;gt; articles = Article.order(&amp;quot;name&amp;quot;)
 =&amp;gt; #&amp;lt;ActiveRecord::Relation:0x00000101669b90 @table=#&amp;lt;Arel::Table:0x000001023e9af8 
@name=&amp;quot;articles&amp;quot;, @options={:engine=&amp;gt;#&amp;lt;Arel::Sql::Engine:0x000001023a15c8 @ar=ActiveRecord::Base,
@adapter_name=&amp;quot;SQLite&amp;quot;&amp;gt;}, @engine=#&amp;lt;Arel::Sql::Engine:0x000001023a15c8 @ar=ActiveRecord::Base,
@adapter_name=&amp;quot;SQLite&amp;quot;&amp;gt;, &amp;hellip;
&lt;/pre&gt; 

&lt;p&gt;Anstatt einer Liste von Artikeln haben wir diesmal ein &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; Objekt zur&amp;uuml;ckbekommen. Dieses Objekt speichert Informationen &amp;uuml;ber unsere Suche, die tats&amp;auml;chliche Anfrage wurde aber noch nicht durchgef&amp;uuml;hrt. Dies ist die Bedeutung von lazy loading in diesem Kontext: Die Daten werden erst abgefragt, wenn es sein muss! Die Anfrage an die Datenbank wird erst durchgef&amp;uuml;hrt, wenn wir explizit eine Datenmenge anfordern (z.B. mit &lt;code&gt;each&lt;/code&gt;, wenn wir alle Artikel auf einmal oder nur den ersten Artikel anfragen w&amp;uuml;rden):&lt;/p&gt;

&lt;pre class="terminal"&gt;
ruby-1.9.1-p378 &amp;gt; articles.first
 =&amp;gt; #&amp;lt;Article id: 2, name: &amp;quot;Can&amp;#x27;t See Me&amp;quot;, published_at: nil, hidden: false, 
created_at: &amp;quot;2010-02-22 20:37:03&amp;quot;, updated_at: &amp;quot;2010-02-22 20:37:03&amp;quot;&amp;gt;
&lt;/pre&gt; 

&lt;p&gt;Betrachten wir nun, inwiefern sich das auf unsere Applikation anwenden l&amp;auml;sst. Wir haben ein Scaffold f&amp;uuml;r Article erzeugen lassen, also haben wir auch einen ArticlesController mit den &amp;uuml;blichen sieben Aktionen. In der &lt;code&gt;index&lt;/code&gt;-Aktion wird &lt;code&gt;Article.all&lt;/code&gt; verwendet, um alle Artikel auf einmal abzufragen:&lt;/p&gt;

&lt;pre class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/pre&gt;
&lt;pre class="ruby"&gt;
def index
  @articles = Article.all

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml =&amp;gt; @articles }
  end
end
&lt;/pre&gt;

&lt;p&gt;Verwenden wir eine der neuen Methoden wie beispielsweise &lt;code&gt;order&lt;/code&gt;, um die Artikel nach dem Namen zu sortieren, wird an Stelle des Arrays mit allen Artikeln ein &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; Objekt in &lt;code&gt;@articles&lt;/code&gt; gespeichert. Das hat zur Folge, dass die eigentliche Datenbankanfrage nicht im Controller, sondern im View durchgef&amp;uuml;hrt wird.&lt;/p&gt;

&lt;pre class="codeFilePath"&gt;/app/views/articles/index.html.erb&lt;/pre&gt;
&lt;pre class="ruby"&gt;
&amp;lt;% @articles.each do |article| %&amp;gt;
  &amp;lt;tr&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= article.name %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= article.published_at %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= article.hidden %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;#x27;Show&amp;#x27;, article %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;#x27;Edit&amp;#x27;, edit_article_path(article) %&amp;gt;&amp;lt;/td&amp;gt;
    &amp;lt;td&amp;gt;&amp;lt;%= link_to &amp;#x27;Destroy&amp;#x27;, article, :confirm =&amp;gt; &amp;#x27;Are you sure?&amp;#x27;, :method =&amp;gt; :delete %&amp;gt;&amp;lt;/td&amp;gt;
  &amp;lt;/tr&amp;gt;
&amp;lt;% end %&amp;gt;
&lt;/pre&gt;

&lt;p&gt;Wenn wir jetzt die Index-Seite aufrufen, werden die Artikel in alphabetischer Reihenfolge dargestellt.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/329/original/E202I01.png" width="798" height="368" alt="The scaffold-generated article index page."/&gt;
&lt;/div&gt;

&lt;p&gt;Sehr angenehm f&amp;auml;llt auf, dass &lt;em&gt;fragment caching&lt;/em&gt; mithilfe der &lt;code&gt;cache&lt;/code&gt;-Methode im View sich jetzt deutlicher auswirken wird, da der &amp;uuml;blicherweise langsame Datenbankzugriff nur dann ausgef&amp;uuml;hrt werden wird, wenn er wirklich notwendig ist.&lt;/p&gt;

&lt;p&gt;Die neue Syntax macht es dar&amp;uuml;ber hinaus auch einfacher, komplexere Suchbedingungen zu vereinen. Nehmen wir an, wir wollen die Artikel filtern, so dass nur die versteckten angezeigt werden, wenn wir &lt;code&gt;hidden=1&lt;/code&gt; als Parameter in der URL &amp;uuml;bergeben. Dies l&amp;auml;sst sich leicht verwirklichen, indem wir den Code in der &lt;code&gt;index&lt;/code&gt;-Aktion wie folgt ver&amp;auml;ndern:&lt;/p&gt;

&lt;pre class="codeFilePath"&gt;/app/controllers/articles_controller.rb&lt;/pre&gt;
&lt;pre class="ruby"&gt;
def index
  @articles = Article.order(&amp;#x27;name&amp;#x27;)
    
  if params[:hidden]
    @articles = @articles.where(:hidden =&amp;gt;(params[:hidden] == &amp;quot;1&amp;quot;))
  end

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml =&amp;gt; @articles }
  end
end
&lt;/pre&gt;

&lt;p&gt;Ist ein &lt;code&gt;hidden&lt;/code&gt;-Parameter vorhanden und hat er den Wert &lt;code&gt;1&lt;/code&gt;, wird eine zus&amp;auml;tzliche &lt;code&gt;where&lt;/code&gt;-Methode an unsere Suche angeh&amp;auml;ngt, so dass die Suche nur noch die versteckten Artikel anzeigen wird. Sobald wir den entsprechenden Parameter an die URL anh&amp;auml;ngen und neu laden, sehen wir nur noch die versteckten Artikel.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/330/original/E202I02.png" width="796" height="280" alt="Showing just the hidden articles."/&gt;
&lt;/div&gt;

&lt;p&gt;&amp;Uuml;bergeben wir hingegen &lt;code&gt;0&lt;/code&gt;, bekommen wir nur die sichtbaren Artikel zu sehen.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/331/original/E202I03.png" width="796" height="280" alt="Now only the visible articles are shown."/&gt;
&lt;/div&gt;

&lt;p&gt;Die M&amp;ouml;glichkeit, verschiedenste Suchmethoden aneinander zu h&amp;auml;ngen, er&amp;ouml;ffnet Wege, mit sehr einfachem Code deutlich komplexere Datenbankabfragen zu formulieren, die auch erst dann tats&amp;auml;chlich ausgef&amp;uuml;hrt werden, wenn die Daten ben&amp;ouml;tigt werden.&lt;/p&gt;

&lt;h3&gt;Named Scopes&lt;/h3&gt;

&lt;p&gt;Als N&amp;auml;chstes werden wir einige der &amp;Auml;nderungen zu &lt;em&gt;Named Scopes&lt;/em&gt; in Rails 3 betrachten. Als Beispiel dient uns unser Model &lt;code&gt;Article&lt;/code&gt; mit zwei Named Scopes, einer f&amp;uuml;r die sichtbaren Artikel und einer f&amp;uuml;r die ver&amp;ouml;ffentlichten.&lt;/p&gt;

&lt;pre class="codeFilePath"&gt;/app/models/article.rb&lt;/pre&gt;
&lt;pre class="ruby"&gt;
class Article &amp;lt; ActiveRecord::Base
  named_scope :visible, :conditions =&amp;gt; [&amp;quot;hidden != ?&amp;quot;, true]
  named_scope :published, lambda { {:conditions =&amp;gt; [&amp;quot;published_at &amp;lt;= ?&amp;quot;, Time.zone.now]} }
end
&lt;/pre&gt;

&lt;p&gt;Diese Scopes sind im Stil von Rails 2 formuliert, doch in Rails 3 ist die Vorgehensweise leicht unterschiedlich. Der erste Unterschied liegt in der Benennung der Funktion: Sie hei&amp;szlig;t jetzt nicht mehr &lt;code&gt;named_scope&lt;/code&gt;, sondern einfach nur noch &lt;code&gt;scope&lt;/code&gt;. Dar&amp;uuml;ber hinaus werden die Optionen nicht mehr als Hash &amp;uuml;bergeben sondern genau wie beim Wechsel von &lt;code&gt;find&lt;/code&gt; als einzelne Methoden. Genau wie wir die neuen &lt;code&gt;find&lt;/code&gt;-Methoden verwendet haben, verwenden wir hier &lt;code&gt;where&lt;/code&gt; an Stelle von &lt;code&gt;:conditions&lt;/code&gt;. Die Syntax f&amp;uuml;r Named Scopes in Rails 3 sieht also so aus:&lt;/p&gt;

&lt;pre class="codeFilePath"&gt;/app/models/article.rb&lt;/pre&gt;
&lt;pre class="ruby"&gt;
class Article &amp;lt; ActiveRecord::Base
  scope :visible, where(&amp;quot;hidden != ?&amp;quot;, true)
  scope :published, lambda { where(&amp;quot;published_at &amp;lt;= ?&amp;quot;, Time.zone.now) }
end
&lt;/pre&gt;

&lt;p&gt;Ein weiteres neues Feature ist die M&amp;ouml;glichkeit, scopes aufeinander aufzubauen. Wenn wir einen Scope mit dem Namen &lt;code&gt;recent&lt;/code&gt;, der die k&amp;uuml;rzlich ver&amp;ouml;ffentlichten und sichtbaren Artikel nach ihrem Ver&amp;ouml;ffentlichungsdatum sortiert zur&amp;uuml;ckgibt, k&amp;ouml;nnen wir einfach die beiden vorhandenen Scopes wiederverwenden:&lt;/p&gt;

&lt;pre class="ruby"&gt;
scope :recent, visible.published.order(&amp;quot;published_at desc&amp;quot;)
&lt;/pre&gt;

&lt;p&gt;Hier haben wir also zwei bestehende Scopes in einem neuen zusammengef&amp;uuml;hrt und einen &lt;code&gt;order&lt;/code&gt;-Aufruf angeh&amp;auml;ngt. Dieses Verketten von Scopes ist ein sehr praktisches Feature bei der Erzeugung neuer, komplexerer Scopes f&amp;uuml;r unsere Models.&lt;/p&gt;

&lt;p&gt;Probieren wir unseren neuen Scope doch einfach in der Konsole aus. Wenn wir &lt;code&gt;Article.recent&lt;/code&gt; aufrufen, wird uns ein &lt;code&gt;ActiveRecord::NamedScope::Scope&lt;/code&gt; Objekt zur&amp;uuml;ckgegeben. Dieses Objekt verh&amp;auml;lt sich ganz &amp;auml;hnlich wie das &lt;code&gt;ActiveRecord::Relation&lt;/code&gt; Objekt, das wir weiter oben betrachtet haben.&lt;/p&gt;

&lt;pre class="terminal"&gt;
ruby-1.9.1-p378 &amp;gt; Article.recent
 =&amp;gt; #&amp;lt;ActiveRecord::NamedScope::Scope:0x0000010318bd08 @table=#&amp;lt;Arel::Table:0x00000102740ea8 
 @name=&amp;quot;articles&amp;quot;, @options={:engine=&amp;gt;#&amp;lt;Arel::Sql::Engine:0x00000102651900 @ar=ActiveRecord::Base&amp;gt;}, 
 @engine=#&amp;lt;Arel::Sql::Engine:0x00000102651900 @ar=ActiveRecord::Base&amp;gt;&amp;gt;, &amp;hellip;
&lt;/pre&gt;

&lt;p&gt;Wenn wir &lt;code&gt;all&lt;/code&gt; auf dieses Scope Objekt anwenden, sehen wir die passenden Ergebnisse.&lt;/p&gt;

&lt;pre class="terminal"&gt;
ruby-1.9.1-p378 &amp;gt; Article.recent.all
 =&amp;gt; [#&amp;lt;Article id: 1, name: &amp;quot;It&amp;#x27;s Ancient&amp;quot;, published_at: &amp;quot;2010-01-01&amp;quot;, 
 hidden: false, created_at: &amp;quot;2010-02-22 20:35:42&amp;quot;, updated_at: &amp;quot;2010-02-22 23:00:16&amp;quot;&amp;gt;]
&lt;/pre&gt;

&lt;h3&gt;Ein letzter Tipp&lt;/h3&gt;

&lt;p&gt;Beenden wir diese Episode mit einem sehr n&amp;uuml;tzlichen Tipp. Wenn Sie ein &lt;code&gt;Relation&lt;/code&gt; oder ein &lt;code&gt;Scope&lt;/code&gt; Objekt haben und den SQL-Query sehen wollen, den es ausf&amp;uuml;hren w&amp;uuml;rde, k&amp;ouml;nnen Sie einfach die Methode &lt;code&gt;to_sql&lt;/code&gt; aufrufen:&lt;/p&gt;

&lt;pre class="terminal"&gt;
ruby-1.9.1-p378 &amp;gt; Article.recent.to_sql
 =&amp;gt; &amp;quot;SELECT     \&amp;quot;articles\&amp;quot;.* FROM       \&amp;quot;articles\&amp;quot; 
 WHERE     (hidden != &amp;#x27;t&amp;#x27;) AND (published_at &amp;lt;= &amp;#x27;2010-02-22 22:47:12.023289&amp;#x27;) 
 ORDER BY  published_at desc&amp;quot;
&lt;/pre&gt;

&lt;p&gt;Diese Methode gibt den SQL-Code zur&amp;uuml;ck, den ActiveRecord ausf&amp;uuml;hren wird, um die zuletzt ver&amp;ouml;ffentlichten und nicht versteckten Artikel von der Datenbank zu erhalten.&lt;/p&gt;

&lt;p&gt;Das war&amp;#x27;s f&amp;uuml;r diese Episode &amp;uuml;ber ActiveRecord Queries in Rails 3! Es gibt jede Menge Neuerungen, die dabei helfen werden, den Code in Ihren Contollern kompakter und klarer zu formulieren. Es lohnt sich also, ein Wenig mit den neuen Features herumzuspielen!&lt;/p&gt;</description>
      <pubDate>Mon, 01 Mar 2010 23:14:38 +0000</pubDate>
      <guid>http://de.asciicasts.com/episodes/202-active-record-queries-in-rails-3</guid>
      <link>http://de.asciicasts.com/episodes/202-active-record-queries-in-rails-3</link>
    </item>
    <item>
      <title>Bundler</title>
      <description>&lt;p&gt;In dieser Episode f&amp;uuml;hren wir unsere Vorschau auf die neuen Features von Rails 3 fort. Dieses Mal werfen wir einen Blick auf &lt;a href="http://github.com/carlhuda/bundler"&gt;Bundler&lt;/a&gt;, die neue Art, Gem-Abh&amp;auml;ngigkeiten von Rails-Applikationen zu verwalten.&lt;/p&gt;

&lt;p&gt;Bundler wird momentan stetig weiterentwickelt, also geht man am Besten sicher, die aktuellste Version installiert zu haben, indem man&lt;/p&gt;
    
&lt;pre class="terminal"&gt;
gem install bundler
&lt;/pre&gt;

&lt;p&gt;ausf&amp;uuml;hrt. Hierbei bitte beachten, dass nicht &lt;code&gt;sudo&lt;/code&gt; eingesetzt wird, da hier eine mit &lt;code&gt;rvm&lt;/code&gt; installierte Version von Ruby verwendet wird.&lt;/p&gt;

&lt;h3&gt;Wie man Bundler benutzt, um Gems zu installieren&lt;/h3&gt;

&lt;p&gt;In der letzten Episode hatten wir das Problem, dass uns der &lt;code&gt;sqlite3-ruby&lt;/code&gt; Gem gefehlt hatte. Wir haben dieses Problem von Hand gel&amp;ouml;st, indem wir den Gem per &lt;code&gt;gem install&lt;/code&gt; nachinstalliert haben.&lt;/p&gt;

&lt;pre class="terminal"&gt;
gem install sqlite3-ruby
&lt;/pre&gt;

&lt;p&gt;Wir h&amp;auml;tten Dies alternativ auch mit Bundler machen k&amp;ouml;nnen, da in den Abh&amp;auml;ngigkeiten unserer Applikation &lt;code&gt;sqlite3-ruby&lt;/code&gt; aufgef&amp;uuml;hrt ist, also im &lt;code&gt;Gemfile&lt;/code&gt; unserer Applikation aufgelistet ist. Um die Abh&amp;auml;ngigkeiten aufzul&amp;ouml;sen, f&amp;uuml;hren wir &lt;code&gt;bundle install&lt;/code&gt; aus, was alle Eintr&amp;auml;ge durchgeht und sie bei Bedarf nachinstalliert.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ bundle install
Fetching source index from http://gemcutter.org
Resolving dependencies
Installing abstract (1.0.0) from system gems 
Installing actionmailer (3.0.0.beta) from system gems 
Installing actionpack (3.0.0.beta) from system gems 
Installing activemodel (3.0.0.beta) from system gems 
Installing activerecord (3.0.0.beta) from system gems 
Installing activeresource (3.0.0.beta) from system gems 
Installing activesupport (3.0.0.beta) from system gems 
Installing arel (0.2.1) from rubygems repository at http://gemcutter.org 
Installing builder (2.1.2) from system gems 
Installing bundler (0.9.5) from system gems 
Installing erubis (2.6.5) from system gems 
Installing i18n (0.3.3) from system gems 
Installing mail (2.1.2) from system gems 
Installing memcache-client (1.7.8) from system gems 
Installing mime-types (1.16) from system gems 
Installing rack (1.1.0) from system gems 
Installing rack-mount (0.4.7) from rubygems repository at http://gemcutter.org 
Installing rack-test (0.5.3) from system gems 
Installing rails (3.0.0.beta) from system gems 
Installing railties (3.0.0.beta) from system gems 
Installing rake (0.8.7) from system gems 
Installing sqlite3-ruby (1.2.5) from system gems 
Installing text-format (1.0.0) from system gems 
Installing text-hyphen (1.0.0) from system gems 
Installing thor (0.13.1) from rubygems repository at http://gemcutter.org 
Installing tzinfo (0.3.16) from system gems 
Your bundle is complete!
&lt;/pre&gt;

&lt;p&gt;Anhand der Ausgabe kann man erkennen, dass Bundler alle Gems, die von der Applikation ben&amp;ouml;tigt werden, einschlie&amp;szlig;lich &lt;code&gt;sqlite3-ruby&lt;/code&gt; installiert hat. W&amp;auml;re ein Gem noch nicht installiert gewesen, h&amp;auml;tte Bundler ihn von Gemcutter heruntergeladen und nachinstalliert.&lt;/p&gt;

&lt;p&gt;Im Zweifelsfall kann man also einfach immer &lt;code&gt;bundle install&lt;/code&gt; ausf&amp;uuml;hren, um alle Abh&amp;auml;ngigkeiten aufl&amp;ouml;sen zu lassen. Immer, wenn man eine neue Applikation erzeugt oder wenn man auf fremden Code zur&amp;uuml;ckgreift, sollte man dieses Kommando laufen lassen, um sicherzugehen, dass man die richtigen Gems installiert hat. Auch beim Ausliefern einer Applikation sollte diese &amp;Uuml;berpr&amp;uuml;fung auf dem Produktivsystem stattfinden. Man kann das Kommando auch einfach zu seinen &lt;code&gt;deployment recipes&lt;/code&gt; hinzuf&amp;uuml;gen, damit es immer beim Ausliefern automatisch ausgef&amp;uuml;hrt wird.&lt;/p&gt;

&lt;p&gt;Es ist jedoch wichtig, zu beachten, dass man niemals &lt;code&gt;sudo&lt;/code&gt; verwenden sollte, wenn man &lt;code&gt;bundle install&lt;/code&gt; ausf&amp;uuml;hrt, auch wenn es sonst man beim Installieren von Gems normalerweise tut.&lt;/p&gt;

&lt;h3&gt;Gem-Abh&amp;auml;ngigkeiten in einer Applikation registrieren&lt;/h3&gt;

&lt;p&gt;Wie f&amp;uuml;gen wir also solche Abh&amp;auml;ngigkeiten zu unserer Applikation hinzu? In fr&amp;uuml;heren Rails-Versionen wurden diese in der &lt;code&gt;/config/environment.rb&lt;/code&gt;-Datei vermerkt, was sich mit Rails 3 jedoch ge&amp;auml;ndert hat. Die ben&amp;ouml;tigten Gems werden jetzt in einer &lt;code&gt;Gemfile&lt;/code&gt; genannten Datei im Rootverzeichnis der Applikation notiert. Das &lt;code&gt;Gemfile&lt;/code&gt; einer neuen Rails-Applikation sieht so aus:&lt;/p&gt;

&lt;pre class="ruby"&gt;
# Edit this Gemfile to bundle your application&amp;#x27;s dependencies.
source &amp;#x27;http://gemcutter.org&amp;#x27;


gem &amp;quot;rails&amp;quot;, &amp;quot;3.0.0.beta&amp;quot;

## Bundle edge rails:
# gem &amp;quot;rails&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/rails/rails.git&amp;quot;

# ActiveRecord requires a database adapter. By default,
# Rails has selected sqlite3.
gem &amp;quot;sqlite3-ruby&amp;quot;, :require =&amp;gt; &amp;quot;sqlite3&amp;quot;

## Bundle the gems you use:
# gem &amp;quot;bj&amp;quot;
# gem &amp;quot;hpricot&amp;quot;, &amp;quot;0.6&amp;quot;
# gem &amp;quot;sqlite3-ruby&amp;quot;, :require =&amp;gt; &amp;quot;sqlite3&amp;quot;
# gem &amp;quot;aws-s3&amp;quot;, :require =&amp;gt; &amp;quot;aws/s3&amp;quot;

## Bundle gems used only in certain environments:
# gem &amp;quot;rspec&amp;quot;, :group =&amp;gt; :test
# group :test do
#   gem &amp;quot;webrat&amp;quot;
# end
&lt;/pre&gt;

&lt;p&gt;Einige Gems sind in dieser Datei schon vermerkt, einschlie&amp;szlig;lich &lt;code&gt;rails&lt;/code&gt; und &lt;code&gt;sqlite3-ruby&lt;/code&gt;. Besonders beachten sollte man die Versionsnummer in der Zeile, die auf den &lt;code&gt;rails&lt;/code&gt; Gem verweist. Zu jeder Referenz in dieser Datei kann man eine bestimmte Version spezifizieren, um eine ganz bestimmte Version eines Gems verwenden zu lassen. Um zu einem bestimmten Zeitpunkt auf eine neue Rails-Version umzusteigen, muss man die Version einfach in dieser Datei vermerken, anstatt wie fr&amp;uuml;her in der &lt;code&gt;environment.rb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Um zus&amp;auml;tzliche Gems in unserer Applikation zu verwenden, muss man sie einfach nur in dieser Datei vermerken. Beispielsweise kann man &lt;code&gt;will_paginate&lt;/code&gt; so einbinden:&lt;/p&gt;

&lt;pre class="ruby"&gt;
gem &amp;quot;will_paginate&amp;quot;, &amp;quot;&amp;gt;=2.3.12&amp;quot;
&lt;/pre&gt;

&lt;p&gt;Der zweite Parameter gibt an, dass die Version 2.3.12 oder neuer des Gems verwendet werden soll. Sobald dieser Verweis in dem &lt;code&gt;Gemfile&lt;/code&gt; steht, kann man den Gem per &lt;code&gt;bundle install&lt;/code&gt; automatisch installieren lassen, doch vorher kann man mithilfe von &lt;code&gt;bundle check&lt;/code&gt; die Abh&amp;auml;ngigkeiten pr&amp;uuml;fen lassen:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ bundle check
The following dependencies are missing
  * will_paginate (&amp;gt;= 2.3.12, runtime)We can install the missing gems by running bundle install again. 
&lt;/pre&gt;

&lt;p&gt;Um eine Auflistung aller verf&amp;uuml;gbaren Bundle Kommandos zu sehen, gibt man &lt;code&gt;bundle help&lt;/code&gt; ein:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ bundle help
Tasks:
  bundle check        # Checks if the dependencies listed in Gemfile are satisfied by currently installed gems
  bundle exec         # Run the command in context of the bundle
  bundle help [TASK]  # Describe available tasks or one specific task
  bundle init         # Generates a Gemfile into the current working directory
  bundle install      # Install the current environment to the system
  bundle lock         # Locks the bundle to the current set of dependencies, including all child dependencies.
  bundle pack         # Packs all the gems to vendor/cache
  bundle show         # Shows all gems that are part of the bundle.
  bundle unlock       # Unlock the bundle. This allows gem versions to be changed
&lt;/pre&gt;

&lt;h3&gt;Andere M&amp;ouml;glichkeiten des Gemfiles&lt;/h3&gt;

&lt;p&gt;Betrachten wir weiterhin das &lt;code&gt;Gemfile&lt;/code&gt; und was wir noch damit machen k&amp;ouml;nnen. Ein sehr n&amp;uuml;tzliches neues Feature ist die M&amp;ouml;glichkeit, Gems direkt aus einem &lt;code&gt;git&lt;/code&gt; repository zu bekommen. Um beispielsweise immer auf dem aktuellsten Stand der Entwicklung zu sein, kann man den &lt;code&gt;rails&lt;/code&gt; Gem auf das zentrale Entwicklungs-repository verweisen lassen:&lt;/p&gt;

&lt;pre class="ruby"&gt;
# Bundle edge rails:
gem &amp;quot;rails&amp;quot;, :git =&amp;gt; &amp;quot;git://github.com/rails/rails.git&amp;quot;
&lt;/pre&gt;

&lt;p&gt;Dieses Feature er&amp;ouml;ffnet m&amp;auml;chtige neue M&amp;ouml;glichkeiten! Wenn ein Gem nicht ganz so funktioniert, wie wir uns vorstellen, k&amp;ouml;nnen wir das Projekt auf github forken, den Code nach eigenem Ermessen ver&amp;auml;ndern und die Gem-Abh&amp;auml;ngigkeit auf unser github repository verweisen lassen.&lt;/p&gt;

&lt;p&gt;Man kann Gems allerdings auch auf eine bestimmte Umgebung beschr&amp;auml;nken. Um &lt;code&gt;RSpec&lt;/code&gt; f&amp;uuml;r Testzwecke zu laden, kann man Folgendes notieren:&lt;/p&gt;

&lt;pre class="ruby"&gt;
gem &amp;quot;rspec&amp;quot;, :group =&amp;gt; :test
&lt;/pre&gt;

&lt;p&gt;Wenn man gleich mehrere Gems in einer bestimmten Umgebung laden m&amp;ouml;chte, kann man &lt;code&gt;group&lt;/code&gt; auch einen Block &amp;uuml;bergeben:&lt;/p&gt;

&lt;pre class="ruby"&gt;
group :test do
  gem &amp;quot;webrat&amp;quot;
  get &amp;quot;rspec&amp;quot;
end
&lt;/pre&gt;

&lt;p&gt;L&amp;auml;sst man &lt;code&gt;bundle install&lt;/code&gt; jetzt laufen, werden alle Gems f&amp;uuml;r alle Umgebungen installiert:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ bundle install
Fetching source index from http://gemcutter.org
Resolving dependencies
...
Installing rspec (1.3.0) from rubygems repository at http://gemcutter.org 
...
Installing webrat (0.7.0) from rubygems repository at http://gemcutter.org 
Installing will_paginate (2.3.12) from system gems 
Your bundle is complete!
&lt;/pre&gt;

&lt;p&gt;Wie man der (verk&amp;uuml;rzten) Ausgabe entnehmen kann, wurden die Gems aus unserem &lt;code&gt;Gemfile&lt;/code&gt; installiert.&lt;/p&gt;

&lt;p&gt;Wenn man Gems aus einer bestimmten Umgebung nicht installieren will, verwendet man die Option&lt;code&gt;--without&lt;/code&gt;. Um also alle Gems ohne die aus der &lt;code&gt;test&lt;/code&gt;-Umgebung zu installieren, f&amp;uuml;hrt man Folgendes aus:&lt;/p&gt;

&lt;pre class="terminal"&gt;
bundle install --without=test
&lt;/pre&gt;

&lt;p&gt;Dies ist besonders hilfreich, wenn man seine Applikation auf dem Produktivsystem installieren will, ohne die ganzen Gems, die f&amp;uuml;rs Testen ben&amp;ouml;tigt werden, mitzuinstallieren.&lt;/p&gt;

&lt;h3&gt;Gems sperren&lt;/h3&gt;

&lt;p&gt;Ein weiteres sehr n&amp;uuml;tzliches Kommando ist &lt;code&gt;bundle lock&lt;/code&gt;. Es sperrt die exakten Versionen der Gems, die unsere Applikation nutzt. Nachdem dieses Kommando ausgef&amp;uuml;hrt wurde, existiert eine neue Datei mit dem Namen &lt;code&gt;Gemfile.lock&lt;/code&gt;. Diese Datei listet alle Gems zusammen mit ihrer jeweiligen Version auf, die f&amp;uuml;r unsere Applikation installiert wurden. Nach der Ausf&amp;uuml;hrung von &lt;code&gt;bundle lock&lt;/code&gt; werden durch &lt;code&gt;bundle install&lt;/code&gt; nur noch genau die Gems in den Versionen installiert, die im &lt;code&gt;Gemfile.lock&lt;/code&gt; vermerkt sind, selbst wenn neuere Versionen verf&amp;uuml;gbar sein sollten.&lt;/p&gt;

&lt;p&gt;Wenn man mit anderen Rails-Entwicklern zusammen an einem Projekt arbeitet, kann man &lt;code&gt;bundle lock&lt;/code&gt; verwenden, um sicherzugehen, dass Jeder die gleichen Versionen aller ben&amp;ouml;tigten Gems verwendet. Das Gleiche gilt beim Deployment einer Applikation auf das Produktivsystem. Falls eine Applikation auf einen anderen Server umziehen muss, will man sichergehen, dass exakt die gleichen Voraussetzungen vorherrschen wie auf unserem Entwicklungssystem.&lt;/p&gt;

&lt;p&gt;Muss man zu einem sp&amp;auml;teren Zeitpunkt &amp;Auml;nderungen an den Abh&amp;auml;ngigkeiten vornehmen, sollte man allerdings nicht einfach das &lt;code&gt;Gemfile.lock&lt;/code&gt; ver&amp;auml;ndern. Stattdessen bringt man das &lt;code&gt;Gemfile&lt;/code&gt; auf den gew&amp;uuml;nschten Stand und f&amp;uuml;hrt das &lt;code&gt;bundle install&lt;/code&gt;-Kommando mit der zus&amp;auml;tzlichen Option &lt;code&gt;--relock&lt;/code&gt; aus:&lt;/p&gt;

&lt;pre class="terminal"&gt;
bundle install --relock
&lt;/pre&gt;

&lt;p&gt;Dadurch werden die Gems entsperrt, auf die gew&amp;uuml;nschte Version gebracht und wieder gesperrt.&lt;/p&gt;

&lt;h3&gt;Gems in der Applikation installieren&lt;/h3&gt;

&lt;p&gt;Das letzte zu betrachtende Feature ist &lt;code&gt;bundle pack&lt;/code&gt;. Normalerweise installiert Bundler alle Gems im &lt;code&gt;.bundle&lt;/code&gt;-Verzeichnis im Hauptverzeichnis des aktuellen Benutzers:&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ ls ~/.bundle
cache		doc		gems		ruby		specifications
&lt;/pre&gt;

&lt;p&gt;Daraus folgt nat&amp;uuml;rlich, dass die Gems nicht im Verzeichnis der jeweiligen Applikation liegen und damit auch nicht im verwendeten Versionskontrollsystem landen. M&amp;ouml;chten wir allerdings die Gems mit unserer Anwendung ausliefern, k&amp;ouml;nnen wir &lt;code&gt;bundle pack&lt;/code&gt; verwenden:&lt;/p&gt;

&lt;pre class="terminal"&gt;
bundle pack
Copying .gem files into vendor/cache
  * memcache-client-1.7.8.gem
  * rspec-1.3.0.gem
  * thor-0.13.3.gem
  * tzinfo-0.3.16.gem
  * builder-2.1.2.gem
  * nokogiri-1.4.1.gem
  * mime-types-1.16.gem
  * sqlite3-ruby-1.2.5.gem
  * i18n-0.3.3.gem
  * abstract-1.0.0.gem
  * erubis-2.6.5.gem
  * text-hyphen-1.0.0.gem
  * bundler-0.9.6.gem
  * rake-0.8.7.gem
  * will_paginate-2.3.12.gem
  * text-format-1.0.0.gem
  * rack-1.1.0.gem
  * rack-test-0.5.3.gem
  * webrat-0.7.0.gem
  * rack-mount-0.4.7.gem
  * activesupport-3.0.0.beta.gem
  * mail-2.1.2.gem
  * arel-0.2.1.gem
  * activemodel-3.0.0.beta.gem
  * actionpack-3.0.0.beta.gem
  * actionmailer-3.0.0.beta.gem
  * activerecord-3.0.0.beta.gem
  * activeresource-3.0.0.beta.gem
  * railties-3.0.0.beta.gem
  * rails-3.0.0.beta.gem
&lt;/pre&gt;

&lt;p&gt;Damit werden die &lt;code&gt;.gem&lt;/code&gt;-Dateien, die unsere Applikation verwendet, ins Verzeichnis &lt;code&gt;/vendor/cache&lt;/code&gt; der Applikation kopiert (wobei das Verzeichnis bei Bedarf erzeugt wird, wenn es noch nicht existiert). Alle so gespeicherten Gems werden danach aus diesen &lt;code&gt;.gem&lt;/code&gt;-Dateien installiert, anstatt sie beispielsweise von Gemcutter zu laden. Normalerweise sollte man dieses Feature nicht all zu oft ben&amp;ouml;tigen, doch wenn man in die Situation kommt, dass das Produktivsystem keine M&amp;ouml;glichkeit hat, Gems von Gemcuttoer oder anderen Quellen herunterzuladen, leistet einem &lt;code&gt;bundle pack&lt;/code&gt; gute Dienste.&lt;/p&gt;

&lt;p&gt;Damit beenden wir die aktuelle Episode. Wir hoffen, sie hat Ihnen einen guten &amp;Uuml;berblick vermittelt, wie man Bundler einsetzen kann, um Gems und Abh&amp;auml;ngigkeiten zu verwalten. Nach einer kurzen Einarbeitungszeit kann Bundler die Probleme, die oft mit diesen Abh&amp;auml;ngigkeiten bestanden haben, endg&amp;uuml;ltig zur Vergangenheit geh&amp;ouml;ren lassen.&lt;/p&gt;

&lt;p&gt;Zu guter letzt m&amp;ouml;chten wir Sie noch auf &lt;a href="http://railsplugins.org/"&gt;railsplugins.org&lt;/a&gt; hinweisen, falls Sie sich gefragt haben, welche Gems und Plugins mit Rails 3 funktionieren. Auf dieser Seite k&amp;ouml;nnen Sie Plugins und Gems durchsuchen, ob sie mit Rails 3 und Ruby 1.9 funktionieren.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/328/original/E201I01.png" width="767" height="634" alt="The RailsPlugins website." /&gt;
&lt;/div&gt;

&lt;p&gt;Falls ein Gem als "not working" aufgelistet ist, ist dies eine grossartige M&amp;ouml;glichkeit, einfach mitzuarbeiten! Auf diese Weise k&amp;ouml;nnen Sie mithelfen, so viele Gems und Plugins wie m&amp;ouml;glich f&amp;uuml;r Rails 3 zu portieren.&lt;/p&gt;</description>
      <pubDate>Fri, 26 Mar 2010 21:14:42 +0000</pubDate>
      <guid>http://de.asciicasts.com/episodes/201-bundler</guid>
      <link>http://de.asciicasts.com/episodes/201-bundler</link>
    </item>
    <item>
      <title>Rails 3 Beta and RVM</title>
      <description>&lt;p&gt;Gibt es bessere Wege die 200. Episode zu feiern als einen ersten Eindruck von Rails 3 zu vermitteln? Die erste Betaversion von Rails 3.0 ist gerade ver&amp;ouml;ffentlicht worden und in dieser Episode zeigen wir die Installation und Konfiguration. In den n&amp;auml;chsten Episoden werden wir einen detaillierten Blick auf neue Funktionen werfen. Auch wenn gar keine Upgrades der Applikationen in naher Zukunft geplant sind, mit den neuen Funktionen herumzuprobieren ist die Installation der Betaversion wert.&lt;/p&gt;

&lt;h3&gt;Ruby aktualisieren&lt;/h3&gt;

&lt;p&gt;Rails 3 braucht Ruby 1.8.7 oder neuer, als ersten Schritt schaue nach welche Version du gerade verwendest indem du &lt;code&gt;ruby -v&lt;/code&gt; in einem Terminalfenster eingibst.&lt;/p&gt;

&lt;pre class="terminal"&gt;
$ ruby -v
ruby 1.8.6 (2008-08-11 patchlevel 287) [universal-darwin9.0]
&lt;/pre&gt;

&lt;p&gt;Dieser Computer verwendet Ruby 1.8.6, wir m&amp;uuml;ssen auf eine neuere Version aktualisieren bevor wir weiter machen k&amp;ouml;nnen. Wir werden rvm verwenden, den &lt;a href="http://rvm.beginrescueend.com"&gt;Ruby Version Manager&lt;/a&gt;. Mit rvm k&amp;ouml;nnen wir auf einfache Weise verschiedene Versionen von Ruby verwenden und mit einem einzelnenen Kommando zwischen ihnen hin- und herschalten.&lt;/p&gt; 

&lt;p&gt;Solltest du Windows benutzen, dann musst du ruby manuell installieren, rvm ist dort nicht verf&amp;uuml;gbar. Unter Linux, OS X und anderen
UNIX-basierenden Systemen k&amp;ouml;nnen wir rvm mit den Anweisungen auf der rvm &lt;a href="http://rvm.beginrescueend.com/install/"&gt;Installationsseite&lt;/a&gt; (engl) einrichten und dann folgendes Kommando absetzen:&lt;/p&gt;

&lt;pre class="terminal"&gt;
mkdir -p ~/.rvm/src/ &amp;amp;&amp;amp; cd ~/.rvm/src &amp;amp;&amp;amp; rm -rf ./rvm/ &amp;amp;&amp;amp; git clone git://github.com/wayneeseguin/rvm.git &amp;amp;&amp;amp; cd rvm &amp;amp;&amp;amp; ./install
&lt;/pre&gt;

&lt;p&gt;Nachdem die Kommandos ausgef&amp;uuml;hrt wurden, werden Instruktionen angezeigt wie man die Installation abschliesst. Je nachdem, ob du bash oder zsh verwendest, gibt es verschiedene Hinweise. Nachdem wir die Instruktionen befolgt haben, m&amp;uuml;ssen wir unser Terminalfenster schliessen und neu aufmachen, damit die &amp;Auml;nderungen aktiv werden. Jetzt k&amp;ouml;nnen wir &lt;code&gt;rvm&lt;/code&gt; ausf&amp;uuml;hren und die Ruby Version installieren, die wir wollen.&lt;/p&gt; 
&lt;p&gt;Rails 3.0 ben&amp;ouml;tigt Ruby 1.8.7, l&amp;auml;uft aber auch mit Ruby 1.9.1. Wir sind abenteuerlustig und werden 1.9.1 installieren. Dazu geben wir folgendes ein:&lt;/p&gt;
&lt;pre class="terminal"&gt;
$ rvm install 1.9.1
&lt;/pre&gt;
&lt;p&gt;Dieser Befehl l&amp;auml;dt die Version aus dem Netz, konfiguriert und installiert Ruby 1.9.1. Dieser Prozess dauert einige Zeit. Nach Abschluss k&amp;ouml;nnen wir mit &lt;code&gt;rvm list&lt;/code&gt; feststellen, welche Ruby Versionen wir installiert haben.&lt;/p&gt;

&lt;pre class="terminal"&gt;
noonoo:~ eifion$ rvm list
   ruby-1.9.1-p378 [ x86_64 ]
   system [ x86_64 i386 ppc ]
&lt;/pre&gt;
&lt;p&gt;Wir haben Ruby 1.9.1 installiert und k&amp;ouml;nnen mit folgendem Befehl darauf umschalten.&lt;/p&gt;
&lt;pre class="terminal"&gt;
$ rvm 1.9.1
$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10.2.0]
&lt;/pre&gt;
&lt;p&gt;Die neue Ruby Version bleibt nur solange aktiv bis das Terminalfenster geschlossen wird. Um die neu installierte Version dauerhaft aktiv zu machen k&amp;ouml;nnen wir den Parameter &lt;code&gt;--default&lt;/code&gt; zu &lt;code&gt;rvm&lt;/code&gt; dazuschreiben.&lt;/p&gt;
&lt;pre class="terminal"&gt;
$ rvm 1.9.1 --default
$ ruby -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-darwin10.2.0]
&lt;/pre&gt;
&lt;p&gt;Jetzt k&amp;ouml;nnen wir beliebig viele Terminalfenster auf- und wieder zumachen, Ruby 1.9.1 bleibt aktiv.&lt;/p&gt;

&lt;p&gt;Falls wir irgendwann wieder zu der Ruby Version des Systems retour wollen, dann k&amp;ouml;nnen wir &lt;code&gt;rvm system&lt;/code&gt; absetzen, mit dem Parameter &lt;code&gt;--default&lt;/code&gt; wird auch diese &amp;Auml;nderung dauerhaft aktiviert.&lt;/p&gt;

&lt;h3&gt;Installation von Rails Beta&lt;/h3&gt;

&lt;p&gt;Jetzt haben wir eine Ruby Version mit der wir Rails 3 Beta verwenden k&amp;ouml;nnen. Wir setzen die folgenden 2 Zeilen ab um Rails zu installieren.&lt;/p&gt;
&lt;pre class="terminal"&gt;
gem install tzinfo builder memcache-client rack rack-test rack-mount erubis mail text-format thor bundler i18n
gem install rails --pre
&lt;/pre&gt;
&lt;p&gt;Weil wir eine noch nicht ver&amp;ouml;ffentlichte Version von Rails verwenden wollen m&amp;uuml;ssen wir die Abh&amp;ouml;ngigkeiten selbst installieren, die erste Zeile erledigt das. Bitte beachte dass wir kein &lt;code&gt;sudo&lt;/code&gt; vor den Befehl &lt;code&gt;gem&lt;/code&gt; setzen. Der Grund daf&amp;uuml;r ist die Verwendung von rvm. Die Seite &lt;a href="http://rvm.beginrescueend.com/gems/"&gt;rvm gems page&lt;/a&gt; gibt dazu weitere Informationen.&lt;/p&gt;
&lt;p&gt;Nachdem beide Kommandos ausgef&amp;uuml;hrt wurden haben wir Rails 3.0 installiert und k&amp;ouml;nnen beginnen es auszuprobieren.&lt;/p&gt;

&lt;h3&gt;Rails 3.0 benutzen&lt;/h3&gt;
&lt;p&gt;Zuerst &amp;uuml;berpr&amp;uuml;fen wir ob Rails 3 wirklich installiert wurde mit &lt;code&gt;rails -v&lt;/code&gt;.&lt;/p&gt;
&lt;pre class="terminal"&gt;
$ rails -v
Rails 3.0.0.beta
&lt;/pre&gt;
&lt;p&gt;Wenn du eine Fehlermeldung siehst dann schlie&amp;szlig;e dein Terminalfenster und mache es neu auf und probiere es erneut. Wir werden nun eine einfache Applikation bauen die Spielst&amp;auml;nde abspeichert, wir nennen sie &lt;code&gt;topscore&lt;/code&gt;. Wir erstellen eine Rails 3.0 Applikation auf die gleiche Weise wie bisher:&lt;/p&gt;
&lt;pre class="terminal"&gt;
rails topscore
&lt;/pre&gt;
&lt;p&gt;Aber wenn wir in das Applikationsverzeichnis wechseln und versuchen den Server zu starten bemerken wir den ersten Unterschied.&lt;/p&gt;
&lt;pre class="terminal"&gt;&amp;cedil;
$ script/server
-bash: script/server: No such file or directory
&lt;/pre&gt;
&lt;p&gt;In dem Verzeichnis &lt;code&gt;script&lt;/code&gt; gibt es keine der bisher benutzten Skripte mehr, wie starten wir den Server? Wir benutzen &lt;code&gt;rails&lt;/code&gt; mit dem folgenden Parameter:&lt;/p&gt;
&lt;pre class="terminal"&gt;
rails server
&lt;/pre&gt;
&lt;p&gt;Die nach dem Ausf&amp;uuml;hren des Kommandos angezeigten Fehlermeldungen nehmen wir in Kauf, wir arbeiten mit einer Beta-Release. In den Fehlermeldungen kann man ein fehlendes gem &lt;code&gt;sqlite3-ruby&lt;/code&gt; erkennen. Hier bitte beachten dass jede Ruby Version eigene Pakete von RubyGems verwendet. Deshalb m&amp;uuml;ssen wir das &lt;code&gt;sqlite3-ruby&lt;/code&gt; gem selbst installieren, auch hier wieder ohne &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt; 

&lt;pre class="terminal"&gt;
gem install sqlite3-ruby
&lt;/pre&gt;

&lt;p&gt;Nach einem Start des Servers mit &lt;code&gt;rails server&lt;/code&gt; sehen wir eine Menge an Ausgaben und Warnings, aber der Server startet. Auf der Seite &lt;a href="http://localhost:3000/"&gt;http://localhost:3000&lt;/a&gt; sehen wir die Rails Default Seite.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/326/original/E200I01.png" width="785" height="515" alt="The welcome page for our first Rails 3.0 application."/&gt;
&lt;/div&gt;

&lt;p&gt;Jetzt k&amp;ouml;nnen wir anfangen unsere Applikation zu entwickeln. Wir starten mit einem Scaffold f&amp;uuml;r ein Spiel-Model &lt;code&gt;game&lt;/code&gt; mit einem Attribut &lt;code&gt;name&lt;/code&gt; vom Typ &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;pre class="terminal"&gt;
rails generate scaffold game name:string
&lt;/pre&gt;

&lt;p&gt;Wir lassen uns von den vielen Meldungen nicht abhalten und werden als n&amp;auml;chstes die Datenbank migrieren.&lt;/p&gt;

&lt;pre class="terminal"&gt;
rake db:migrate
&lt;/pre&gt;

&lt;p&gt;Mit einem Browser auf die Applikationssseite zugegriffen, sehen wir die &amp;uuml;blichen per Scaffold generierten Seiten, die du eventuell aus anderen Applikationen kennst.&lt;/p&gt;

&lt;div class="imageWrapper"&gt;
  &lt;img src="/system/photos/327/original/E200I02.png" width="799" height="283" alt="The scaffold-generated new game page."/&gt;
&lt;/div&gt;
&lt;p&gt;Das war es mit unserer Applikation f&amp;uuml;r heute, in sp&amp;auml;teren Episoden werden wir auf neue Funktionen von Rails 3 detaillierter eingehen, in der Zwischenzeit kannst du hier &lt;a href="http://guides.rails.info/3_0_release_notes.html"&gt;Rails 3.0 Release Notes&lt;/a&gt; einen &amp;Uuml;berblick &amp;uuml;ber die &amp;Auml;nderungen bekommen. Es gibt auch eine grosse Sammlung von Links &amp;uuml;ber Rails 3 bei &lt;a href="http://www.rubyinside.com/rails-3-0-beta-links-2966.html"&gt;Ruby Inside&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Beim Arbeiten mit Beta-Software kann es vorkommen, dass Dinge nicht funktionieren und man Fehler und Probleme entdeckt. Falls dir das passiert, und du wei&amp;szlig;t, dass es nichts mit deinem einen Programmcode zu tun hat, dann &amp;uuml;berpr&amp;uuml;fe als allererstes die verwendeten Gems oder Plugins, die deine Applikation verwendet. Die Chancen sind hoch, dass dort das Problem liegt weil das Gem/Plugin (noch) nicht mit Rails 3 oder Ruby 1.9 zusammenarbeitet. Falls du ein Problem einem bestimmten Gem/Plugin zuordnen kannst, dann erstelle bitte ein Ticket auf der Gem Projektseite, damit der Fehler behoben werden kann.&lt;/p&gt;

&lt;p&gt;Falls das Problem bei Rails selbst liegt kannst du beim &lt;a href="https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets?q=all"&gt;Rails Lighthouse&lt;/a&gt; ein Ticket erstellen. Falls du einen Fehler meldest, beachte bitte die folgenden Tipps: Such in bestehenden Tickets, ob das Problem nicht bereits existent ist. Erstelle eine Anleitung zum reproduzieren des Fehlers, f&amp;uuml;ge deine Fehlermeldungen und einen stack trace hinzu. Bitte notiere auch die Version von Ruby on Rails, die du zusammen mit den eingebundenen Gems verwendest, damit es leichter wird, das Problem nachzuvollziehen. Gut beschriebene Fehler in Tickets erleichtern die Behebung des Problems.&lt;/p&gt;

&lt;h3&gt;Gib etwas an Freie Software zur&amp;uuml;ck&lt;/h3&gt;
&lt;p&gt;Wie du vielleicht schon bemerkt hast ist dies die 200. Episode. Um den 200. Screencast hervorzuheben startet Ryan Bates eine Kampagne namens &lt;a href="http://railscasts.com/give_back"&gt;&amp;ldquo;Give Back To Open Source&amp;rdquo;&lt;/a&gt;. Open Source Software entsteht durch viel Arbeit und ist frei erh&amp;auml;ltlich, somit macht es Sinn f&amp;uuml;r jedermann, sich daran zu beteiligen und etwas zur&amp;uuml;ck zu geben. Ryan&amp;rsquo;s Herausforderung an Dich ist es, Deine gr&amp;ouml;sste Rails Applikation zu  &amp;ouml;ffnen und die verschiedenen Plug-ins und Gems zu getrachten, die es benutzt. Viele Gems Projektseiten akzeptieren Spenden, und jeder auch noch so kleine Beitrag wird sehr gesch&amp;auml;tzt, da er dabei hilft, die Entwicklung des Gems am Laufen zu halten.&lt;/p&gt;

&lt;p&gt;Eine andere M&amp;ouml;glichkeit ist es, sich die Liste der Probleme f&amp;uuml;r das Projekt anzusehen, sich damit zu besch&amp;auml;ftigen, einen Bug zu beheben oder bei der Dokumentation zu helfen. Es liegt an Dir, Dich f&amp;uuml;r eine M&amp;ouml;glichkeit zu entscheiden, um beizutragen, aber es ist sehr erw&amp;uuml;nscht, da es der Rails Community hilft, voranzukommen.&lt;/p&gt;</description>
      <pubDate>Mon, 01 Mar 2010 22:56:26 +0000</pubDate>
      <guid>http://de.asciicasts.com/episodes/200-rails-3-beta-and-rvm</guid>
      <link>http://de.asciicasts.com/episodes/200-rails-3-beta-and-rvm</link>
    </item>
  </channel>
</rss>
