<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="de-DE" xmlns="http://www.w3.org/2005/Atom">
  <title>rails::Notes - All</title>
  <id>tag:rnotes.bluemars.net,2010:mephisto/</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://rnotes.bluemars.net/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://rnotes.bluemars.net/" rel="alternate" type="text/html"/>
  <updated>2009-07-23T06:37:55Z</updated>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-07-23:259</id>
    <published>2009-07-23T06:29:00Z</published>
    <updated>2009-07-23T06:37:55Z</updated>
    <category term="Misc"/>
    <category term="apache"/>
    <category term="deflate"/>
    <category term="expires"/>
    <category term="passenger"/>
    <link href="http://rnotes.bluemars.net/259" rel="alternate" type="text/html"/>
    <title>One-Click Speedup f&#252;r Apache-VHosts</title>
<content type="html">
            &lt;p&gt;Mit diesen allgemeinen Apache2-Optionen lässt sich relativ schnell und schmerzlos eine Verbesserung der Ladezeiten erreichen: Kompression und Expiration-Headers.&lt;/p&gt;


	&lt;p&gt;Die beiden verantwortlichen Module müssen aktiviert werden:&lt;/p&gt;


&lt;pre&gt;a2enmod expires
a2enmod deflate&lt;/pre&gt;

	&lt;p&gt;und die globale Sektion der apache2.conf erweitert:&lt;/p&gt;


&lt;pre&gt;# gzip html, css and js
AddOutputFilterByType DEFLATE text/html text/css application/x-javascript application/javascript

# far future expires headers
&amp;lt;FilesMatch &quot;.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf)?d{10}$&quot;&amp;gt;
  ExpiresDefault &quot;access plus 10 years&quot; 
&amp;lt;/FilesMatch&amp;gt;&lt;/pre&gt;

	&lt;p&gt;Zu beachten wäre, dass die statischen Dateien aufgrund der langen Lebensdauer nicht aus dem Cache der Browser verschwinden werden &#8211; es sei denn, man zwingt sie dazu!&lt;/p&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;p&gt;&lt;a href=&quot;http://almosteffortless.com/2009/06/11/speed-up-your-apachepassenger-rails-app-in-2min/&quot;&gt;speed-up-your-apachepassenger-rails-app-in-2min&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-06-13:258</id>
    <published>2009-06-13T16:24:00Z</published>
    <updated>2009-06-13T17:04:14Z</updated>
    <category term="Gems"/>
    <category term="Testing"/>
    <category term="curl"/>
    <category term="fakeweb"/>
    <category term="nokogiri"/>
    <category term="open-uri"/>
    <link href="http://rnotes.bluemars.net/258" rel="alternate" type="text/html"/>
    <title>Fake-a-web</title>
<content type="html">
            &lt;p&gt;Das &lt;em&gt;fakeweb&lt;/em&gt; gem &#8230;&lt;/p&gt;


&lt;pre&gt;gem install fakeweb&lt;/pre&gt;

	&lt;p&gt;... ist quasi für&#8217;s Web, was Mocks und Stubs für die Modelle &#8211; in Spec-Läufen kann man &lt;em&gt;fakewebs&lt;/em&gt; für einzelne URLs definieren. Bei Net::HTTP-Aufrufen wird dann anstelle der richtigen Netzverbindung der vorher definierte lokale Inhalt ausgegeben.&lt;/p&gt;


	&lt;p&gt;Ich benutze Factory-Girl als Fixtureersatz und habe die Webdefinitionen fauler Weise mit in deren Datei spec/factories.rb gegeben, weil ich das irgendwie passend fand:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;page1 = open(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;./spec/www_google_de.txt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) {|f| f.read }&lt;tt&gt;
&lt;/tt&gt;page2 = open(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;./spec/www_google_de_en.txt&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) {|f| f.read }&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;FakeWeb&lt;/span&gt;.register_uri(&lt;span class=&quot;sy&quot;&gt;:get&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://www.google.de&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;tt&gt;
&lt;/tt&gt;                      [{&lt;span class=&quot;sy&quot;&gt;:string&lt;/span&gt; =&amp;gt; page1, &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], &lt;span class=&quot;sy&quot;&gt;:times&lt;/span&gt; =&amp;gt; &lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;},&lt;tt&gt;
&lt;/tt&gt;                       {&lt;span class=&quot;sy&quot;&gt;:string&lt;/span&gt; =&amp;gt; page2, &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], &lt;span class=&quot;sy&quot;&gt;:times&lt;/span&gt; =&amp;gt; &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;},&lt;tt&gt;
&lt;/tt&gt;                       {&lt;span class=&quot;sy&quot;&gt;:string&lt;/span&gt; =&amp;gt; page1, &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;], &lt;span class=&quot;sy&quot;&gt;:times&lt;/span&gt; =&amp;gt; &lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;}])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;FakeWeb&lt;/span&gt;.register_uri(&lt;span class=&quot;sy&quot;&gt;:get&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;http://www.google.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:string&lt;/span&gt; =&amp;gt; &lt;tt&gt;
&lt;/tt&gt;                      &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;google.com here!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:status&lt;/span&gt; =&amp;gt; [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;OK&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;])&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;FakeWeb&lt;/span&gt;.allow_net_connect = &lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Hier werden zwei unterschiedliche Adressen definiert, die erste mit dem Inhalt zweier vorher durch&lt;/p&gt;


&lt;pre&gt;curl -is http://www.google.de/ &amp;gt; ./spec/www_google_de.txt
curl -is http://www.google.de/ncr &amp;gt; ./spec/www_google_de_en.txt&lt;/pre&gt;

	&lt;p&gt;erzeugter Dateien. Indem man der Methode register_uri ein Parameterhash übergibt, kann man eine Rotation des Antwortverhaltens erreichen. Es würde also die ersten vier Male der Inhalt der &lt;em&gt;page1&lt;/em&gt; zurückgegeben, danach der von &lt;em&gt;page2&lt;/em&gt; etc. Nachdem das Array einmal &#8220;verbraucht&#8221; wurde, reagiert das System immer mit dem letzten Eintrag.&lt;/p&gt;


	&lt;p&gt;Will man auf eine Anfrage mit einem String antworten, so geht dies natürlich auch (siehe google.com).&lt;/p&gt;


	&lt;p&gt;Um sicherzugehen, dass während der Tests keine anderen Verbindungen geöffnet werden, kann man diese mit &lt;code&gt;allow_net_connect = false&lt;/code&gt; blockieren. Der Verbindungsversuch an eine undefinierte Adresse wirft dann einen Fehler.&lt;/p&gt;


	&lt;p&gt;Der Model-Code, der schließlich die Netzanrufe auslöst, sieht beim mir so aus:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;doc = &lt;span class=&quot;co&quot;&gt;Nokogiri&lt;/span&gt;::HTML(open(&lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.rwatch_url)).css(&lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.css_selector)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Das &lt;em&gt;open&lt;/em&gt; ist einfach das aus &lt;em&gt;open-uri&lt;/em&gt;.
(Nokogiri ist übrigens ein hervorragender Ersatz für hpricot.)&lt;/p&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;p&gt;&lt;a href=&quot;http://github.com/chrisk/fakeweb/tree/master&quot;&gt;github.com/chrisk/fakeweb&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-06-10:257</id>
    <published>2009-06-10T17:29:00Z</published>
    <updated>2009-06-13T16:55:23Z</updated>
    <category term="Gems"/>
    <category term="Testing"/>
    <category term="autospec"/>
    <category term="autotest"/>
    <category term="cucumber"/>
    <category term="growl"/>
    <category term="libnotify"/>
    <category term="notify"/>
    <link href="http://rnotes.bluemars.net/257" rel="alternate" type="text/html"/>
    <title>autotest-Notifications f&#252;r rspec/cucumber</title>
<content type="html">
            &lt;p&gt;Die Anzeige von &lt;em&gt;Notifications&lt;/em&gt; beim Lauf von &lt;em&gt;autospec&lt;/em&gt; ist ein hübsches Extra, aber leider durch die unterschiedliche Einbindung in die verschiedenen Umgebungen (bei mir Ubuntu und OsX) ab und zu mit Fallstricken verbunden. Hier ist für beide Welten geschildert, wie&#8217;s bei mir läuft:&lt;/p&gt;


	&lt;h4&gt;Ubuntu&lt;/h4&gt;


	&lt;p&gt;Um unter Gnome oder Xfce4 die Ergebnisse ins Desktop einzublenden, benötigt man die &lt;em&gt;libnotify&lt;/em&gt;-Bibliothek:&lt;/p&gt;


&lt;pre&gt;# apt-get install libnotify-bin libnotify1&lt;/pre&gt;

	&lt;p&gt;Danach sollte dieser Test funktionieren:&lt;/p&gt;


&lt;pre&gt;$ notify-send Test &quot;Testtest, 23...&quot;&lt;/pre&gt;

	&lt;p&gt;Um mit dem Notify-Dienst Kontakt aufzunehmen, müssen ein paar Hooks in die &lt;em&gt;.autotest&lt;/em&gt;-Datei gesetzt werden &#8211; leider habe ich es bisher nicht hinbekommen, außer den rspec-Meldungen auch die cucumber-Meldungen anzeigen zu lassen. In der ~/.autotest:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;autotest/timestamp&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;Autotest::GnomeNotify&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;pc&quot;&gt;self&lt;/span&gt;.notify title, msg, img&lt;tt&gt;
&lt;/tt&gt;    system &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;notify-send '&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;title&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;' '&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;msg&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;' -i &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;img&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; -t 5000&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;co&quot;&gt;Autotest&lt;/span&gt;.add_hook &lt;span class=&quot;sy&quot;&gt;:ran_command&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |at|&lt;tt&gt;
&lt;/tt&gt;    image_root = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;~/.autotest_images&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    r = results = [at.results].flatten.join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    results.gsub!(&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\[&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+m&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    output = results.slice(&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\s&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;examples?,&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\s&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\d&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;+)&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\s&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;failures?&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    puts output.inspect&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; output&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;gv&quot;&gt;$~&lt;/span&gt;[&lt;span class=&quot;i&quot;&gt;2&lt;/span&gt;].to_i &amp;gt; &lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        notify &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;FAIL&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;output&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;image_root&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/fail.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        notify &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Pass&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;output&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;image_root&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/pass.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      notify &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;FAIL&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;You must have a non-rspec error in your code.&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&lt;tt&gt;
&lt;/tt&gt;          Check the autotest log for details.&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;image_root&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/fail.png&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt; &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;Autotest&lt;/span&gt;.add_hook &lt;span class=&quot;sy&quot;&gt;:initialize&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |at|&lt;tt&gt;
&lt;/tt&gt;  at.add_exception &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%r%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/tmp&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;%&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  at.add_exception &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%r%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/log&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;%&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  at.add_exception &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;%r%&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/db&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;%&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Insbesondere bei der Verwendung von sqlite-DBs, die unter ./db liegen, hat sich das explizite Ignorieren dieses Verzeichnisses als nötig erwiesen: &lt;em&gt;autospec&lt;/em&gt; läuft sonst unaufhörlich, da beim Testlauf die Datenbankfiles geändert werden.&lt;/p&gt;


	&lt;h4&gt;Mac&lt;/h4&gt;


	&lt;p&gt;Die Kombination &lt;em&gt;autotest-fsevent&lt;/em&gt; und &lt;em&gt;autotest-growl&lt;/em&gt; von BitCetera ist sehr zu empfehlen. &lt;em&gt;autotest-fsevent&lt;/em&gt; verwendet auf Leopard-Maschinen die FsEvent-Mechanik und entlastet so die &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt; dadurch, dass nicht unaufhörlich nach Fileänderungen gesucht werden muss.&lt;/p&gt;


&lt;pre&gt;sudo gem install autotest-fsevent
sudo gem install autotest-growl&lt;/pre&gt;

&lt;pre&gt;~ &amp;gt; cat .autotest 
require 'autotest/growl'
# fsevent als letztes(!):
require 'autotest/fsevent'&lt;/pre&gt;

	&lt;p&gt;Tip: ein eventuell zusätzlich vorhandenes &lt;em&gt;ZenTest&lt;/em&gt; &amp;lt; 4.1.1 sollte man explizit deinstallieren. Dies killt i.d.R. auch die Binaries einer neueren Version, so dass danach in jedem Falle ein erneutes&lt;/p&gt;


&lt;pre&gt;gem install ZenTest&lt;/pre&gt;

	&lt;p&gt;fällig ist.&lt;/p&gt;


	&lt;h4&gt;Teststart&lt;/h4&gt;


	&lt;p&gt;Bevor&#8217;s losgeht, sollte man noch folgende zwei Variablen in die Systemumgebung bringen (z.B. in der .bashrc):&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;AUTOFEATURE=true
RSPEC=true&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Auf beiden Systemen wird der kontinuierliche jetzt Test so gestartet:&lt;/p&gt;


&lt;pre&gt;RAILS_ENV=test autospec 2&amp;gt;/dev/null&lt;/pre&gt;

	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.bitcetera.com/en/techblog/2009/05/27/mac-friendly-autotest/&quot;&gt;www.bitcetera.com/.../mac-friendly-autotest/&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.bitcetera.com/en/products/autotest-fsevent&quot;&gt;www.bitcetera.com/.../autotest-fsevent&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/svoop/autotest-growl/tree/master&quot;&gt;github.com/svoop/autotest-growl&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/svoop/autotest-fsevent/tree/master&quot;&gt;github.com/svoop/autotest-fsevent&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-06-06:256</id>
    <published>2009-06-06T17:20:00Z</published>
    <updated>2009-06-06T17:27:33Z</updated>
    <category term="Gems"/>
    <category term="Misc"/>
    <category term="backup"/>
    <category term="ec2"/>
    <category term="mysqldump"/>
    <category term="postgresql"/>
    <category term="s3"/>
    <category term="tar"/>
    <link href="http://rnotes.bluemars.net/256" rel="alternate" type="text/html"/>
    <title>Astrails &quot;safe&quot; kann jetzt auch PostgreSQL</title>
<content type="html">
            &lt;p&gt;Das &lt;em&gt;safe&lt;/em&gt;-gem der Firma Astrails führt regelmäßige revisionierte Backups von Ordnern und Datenbanken durch. Es bietet einem dabei eine kompakte &lt;span class=&quot;caps&quot;&gt;DSL&lt;/span&gt; und kann die Daten wahlweise verschlüsseln und auf S3-Buckets duplizieren.&lt;/p&gt;


	&lt;p&gt;Kürzlich ist der Support für PostgreSQL-Datenbanken dazugekommen und damit eignet sich die Sache vielleicht für unser Firmenwiki. Ich habe als ersten Test meinen &lt;span class=&quot;caps&quot;&gt;EC2&lt;/span&gt;-Host mit diesem Blog aufgetakelt, den ich bisher &lt;em&gt;nur&lt;/em&gt; mit manuellen &lt;em&gt;tars&lt;/em&gt; und &lt;em&gt;mysqldumps&lt;/em&gt; gesichert hatte.&lt;/p&gt;


	&lt;h4&gt;die Installation&lt;/h4&gt;


	&lt;p&gt;Man nimmt direkt die github-Version und erzeugt eine default-Konfiguration:&lt;/p&gt;


&lt;pre&gt;# gem install astrails-safe --source http://gems.github.com/
Successfully installed astrails-safe-0.1.9
1 gem installed
Installing ri documentation for astrails-safe-0.1.9...
Installing RDoc documentation for astrails-safe-0.1.9...

# astrails-safe /root/my-backup.conf
ERROR: Created default /root/my-backup.conf. Please edit and run again.&lt;/pre&gt;

	&lt;h4&gt;Konfiguration&lt;/h4&gt;


	&lt;p&gt;Es folgt eine Beispielkonfiguration in Ausschnitten &#8211; das default-File ist gut kommentiert:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;safe &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  local &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    path &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/mnt/backup/:kind&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  s3 &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    key &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;my-Amazon-Key-here&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    secret &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;my-secret-Amazon-secret-here&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    bucket &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;the-bucket-name&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    path &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;backups/:kind/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# this is default&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  gpg &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    key &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;fw@bm.net&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  keep &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    local &lt;span class=&quot;i&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# keep 4 local backups&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    s3 &lt;span class=&quot;i&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;c&quot;&gt;# keep 20 S3 backups&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  mysqldump &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    options &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;-ceKq --single-transaction --create-options&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    user &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    password &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;p4ssw0rd&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    socket &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/var/run/mysqld/mysqld.sock&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    database &lt;span class=&quot;sy&quot;&gt;:mephisto&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  tar &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    archive &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;etc-files&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      files &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/etc&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    archive &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;root-files&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      files &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/root&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    archive &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;mephisto&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      files &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/var/www/mephisto/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      exclude [&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/var/www/mephisto/log&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/var/www/mephisto/tmp&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Wie man sieht, ist das Ganze recht übersichtlich. Damit die gpg-Verschlüsselung funktioniert, benötigen wir ein Schlüsselpaar:&lt;/p&gt;


	&lt;h4&gt;gpg-Schlüsselpaar erzeugen&lt;/h4&gt;


	&lt;p&gt;Anfangs hatte ich die symmetrische Verschlüsselung mit einem Passwort versucht, aber das hat mit der Version 1.9 des gem nicht so recht geklappt &#8211; wenn man ein Schlüsselpaar spendiert, funktioniert es aber prima. Das Paar erzeugt man am Besten auf einem anderen Rechner und kopiert nur den öffentlichen Schlüssel auf den Backup-Host.&lt;/p&gt;


&lt;pre&gt;&amp;gt; gpg --key-gen
...
&amp;gt; gpg -a --export fw@bm.net &amp;gt; fw@bm.net.pub
&amp;gt; scp fw@bm.net.pub root@sat.bm.net:/root/
&lt;/pre&gt;

	&lt;p&gt;Auf dem Backup-Host (hier sat.bm.net) wird der öffentliche Schlüssel in den Schlüsselring des Backup-Users importiert (hier root) und als vertrauenswürdig eingestuft:&lt;/p&gt;


&lt;pre&gt;# gpg --import fw@bm.net.pub
gpg: key 45CA9403: public key &quot;F.W. fw@bm.net&quot; imported
gpg: Total number processed: 1
gpg:               imported: 1

# gpg --edit-key fw@bm.net
...
Command&amp;gt; trust
...
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
...
Command&amp;gt; quit&lt;/pre&gt;

	&lt;p&gt;Wer möchte, kann auf dem lokalen Rechner noch eine Kopie des privaten Schlüssels anfertigen &#8211; nur für den Fall:&lt;/p&gt;


&lt;pre&gt;$ gpg -a --export-secret-key fw@bm.net &amp;gt; fw@bm.net.key&lt;/pre&gt;

	&lt;h4&gt;die Automation&lt;/h4&gt;


	&lt;p&gt;Das wär&#8217;s schon. Es fehlt nur noch die Automation via crond &#8211; z.B. morgens, etwa um drei Uhr:&lt;/p&gt;


&lt;pre&gt;10 3 * * * /opt/ruby-enterprise/bin/astrails-safe /root/my-backup.conf &amp;gt;/dev/null 2&amp;gt;&#38;1&lt;/pre&gt;

	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://blog.astrails.com/2009/5/21/postgress-and-svndump-support-for-astrails-safe-s3-backup&quot;&gt;postgress-and-svndump-support-for-astrails-safe-s3-backup&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/astrails/safe/tree/master&quot;&gt;github.com/astrails/safe&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-06-05:255</id>
    <published>2009-06-05T10:51:00Z</published>
    <updated>2009-06-05T10:52:12Z</updated>
    <category term="Gems"/>
    <category term="Plugins"/>
    <category term="Rails"/>
    <category term="memcached"/>
    <category term="safe-erb"/>
    <category term="sql-injection"/>
    <category term="untaint"/>
    <category term="xss"/>
    <link href="http://rnotes.bluemars.net/255" rel="alternate" type="text/html"/>
    <title>10 Minuten-Railssicherheit</title>
<content type="html">
            &lt;p&gt;Den Vortrag &#8220;Security &#8211; What rails will and won’t do for you&#8221; von Rory McCune im Rahmen von &lt;em&gt;Scotland On Rails 2009&lt;/em&gt; habe ich zum Anlass genommen, den überfälligen Aspekt &lt;em&gt;Sicherheit&lt;/em&gt; in meinem laufenden Railsprojekt anzugehen. Der Sprecher benennt &lt;span class=&quot;caps&quot;&gt;XSS&lt;/span&gt;- und &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;-Injection-Angriffe als das bei weitem gewichtigste Problem in diesem Zusammenhang.&lt;/p&gt;


	&lt;h4&gt;&lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;-Injection&lt;/h4&gt;


	&lt;p&gt;Solange man keine ungeprüften Daten, die potentiell aus Usereingaben stammen in Sql-Statements manuell verpackt, sorgt ActiveRecord dafür, dass alles automatisch &lt;em&gt;sanitized&lt;/em&gt; wird. Insofern ist hier Entwarnung angesagt. Konkret heißt das, wenn direktes &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; erzeugt wird, dann &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;NICHT&lt;/span&gt;&lt;/strong&gt; so:&lt;/p&gt;


&lt;pre&gt;&quot;name='#{@user.name}' and user_id='#{@user.id}'&quot;&lt;/pre&gt;

	&lt;p&gt;sondern &lt;strong&gt;SO&lt;/strong&gt;:&lt;/p&gt;


&lt;pre&gt;[&quot;name='%s' and user_id='%s'&quot;, @user.name, @user.id]&lt;/pre&gt;

	&lt;h4&gt;Strategien gegen Cross-Site-Scripting&lt;/h4&gt;


	&lt;p&gt;Hier schlägt man uns zwei Möglichkeiten vor:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Prüfung  von Userdaten bei der Eingabe&lt;/li&gt;
		&lt;li&gt;Prüfung bei der Ausgabe&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Für beide Varianten gibt es Plugins (siehe die Weblinks).  Ich habe mich für die zweite Möglichkeit entschieden und &lt;em&gt;safe-erb&lt;/em&gt; installiert:&lt;/p&gt;


&lt;pre&gt;script/plugin install git://github.com/abedra/safe-erb&lt;/pre&gt;

	&lt;p&gt;Es wirft bei jeder un-sanitizeten Ausgabe eines Strings, der aus DB- oder File-IOs stammt eine Fehlermeldung. Das macht das unbeabsichtigte Übergehen von Lücken schwierig. Die h-Helfermethode Escape-t Tags:&lt;/p&gt;


&lt;pre&gt;&amp;lt;%=h @user.name %&amp;gt;&lt;/pre&gt;
oder
&lt;pre&gt;&amp;lt;%= h(@user.name) %&amp;gt;&lt;/pre&gt;

	&lt;p&gt;und sorgt dafür, dass &lt;em&gt;tainted&lt;/em&gt; Strings &lt;em&gt;untainted&lt;/em&gt; werden, d.h. durch die Prüfung kommen.&lt;/p&gt;


	&lt;p&gt;Zwei Tücken musste ich überwinden:&lt;/p&gt;


	&lt;p&gt;a) Daten die mit dem Rails-Fragmentcaching in &lt;em&gt;memcached&lt;/em&gt; gespeichert werden, werden automatisch &lt;em&gt;tainted&lt;/em&gt;, d.h. als potentiell unsicher eingestuft. Das ist nicht hilfreich, weil die Fragmente natürlich Tags enthalten. J. Roller schlägt in seinem Blog folgende Lösung vor, die die Ausgaben direkt in der memcached-Anbindung &lt;em&gt;untaint&lt;/em&gt;-et. Sie wird z.B. in einem Initializer eingetragen:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;ActiveSupport::Cache::MemCacheStore&lt;/span&gt;   &lt;tt&gt;
&lt;/tt&gt;  logger.info &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Installing Memcache-safe_erb Patch&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;read_with_untaint&lt;/span&gt;(*args)&lt;tt&gt;
&lt;/tt&gt;    read_without_untaint(*args).untaint&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  alias_method_chain &lt;span class=&quot;sy&quot;&gt;:read&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:untaint&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;b) Bei der Einbettung von Javascript-Schnipseln gab es teilweise Probleme &#8211; auch hier darf man natürlich nicht die h-Methode von Rails benutzen, die Tags entfernt, sondern muss den Ergebnisstring untainten:&lt;/p&gt;


&lt;pre&gt;&amp;lt;%= (observe_field &quot;project_active_#{project.id}&quot;, ..., :method =&amp;gt; :post).untaint %&amp;gt;&lt;/pre&gt;

	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.mccune.org.uk/&quot;&gt;www.mccune.org.uk&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/abedra/safe-erb/tree/master&quot;&gt;github.com/abedra/safe-erb&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/sanitizeparams/&quot;&gt;code.google.com/sanitizeparams&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/xssterminate/&quot;&gt;code.google.com/xssterminate&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project&quot;&gt;www.owasp.org/Category:OWASP_Top_Ten_Project&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.jroller.com/bokmann/entry/fixing_safe_erb_with_memcached&quot;&gt;www.jroller.com/../fixing_safe_erb_with_memcached&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-06-03:254</id>
    <published>2009-06-03T09:57:00Z</published>
    <updated>2009-06-03T12:40:45Z</updated>
    <category term="Gems"/>
    <category term="Misc"/>
    <category term="Rails"/>
    <category term="debug"/>
    <category term="ruby_debug"/>
    <category term="vim"/>
    <link href="http://rnotes.bluemars.net/254" rel="alternate" type="text/html"/>
    <title>ruby- (und Rails-) Projekte mit dem vim debuggen</title>
<content type="html">
            &lt;p&gt;Anton Astashov hat kürzlich ein Plugin für vim veröffentlicht, mit dem man ruby- und Rails-Projekte aus dem Editor heraus debuggen kann. Mit&lt;/p&gt;


&lt;pre&gt;:Rdebugger&lt;/pre&gt;

	&lt;p&gt;startet man den Mechanismus. Im Falle eines Railsprojektes wird dann ein Mongrel im development-Modus durch den Debugger gestartet. Auf den kann man wie üblich mit dem Webbrowser zugreifen. Hat man Breakpoints gesetzt, so hält der Prozess an der Stelle an und vim zeigt sie im Hauptfenster.&lt;/p&gt;


	&lt;p&gt;Nun kann man sich die aktiven Variablen ansehen und schrittweise durch den Quelltext gehen:&lt;/p&gt;


	&lt;p&gt;&lt;/p&gt;


	&lt;h4&gt;Installation&lt;/h4&gt;


	&lt;p&gt;Damit die Sache funktioniert, muss der vim mit &#8220;1&#8221; antworten, wenn man ihn dies fragt:&lt;/p&gt;


&lt;pre&gt;:echo has(&quot;signs&quot;) &#38;&#38; has(&quot;clientserver&quot;) &#38;&#38; v:version &amp;gt; 700&lt;/pre&gt;

	&lt;p&gt;Weder der eingebaute vim in Leopard noch der port-vim bringen im Moment eine Unterstützung für das Feature &lt;em&gt;clientserver&lt;/em&gt; mit, aber die gvim- und MacVim-Varianten, die ich in Ubuntu und OsX ausprobiert habe, funktionierten beide klaglos.&lt;/p&gt;


	&lt;p&gt;Außerdem wird das &lt;em&gt;ruby-debug-ide&lt;/em&gt; gem genötigt.&lt;/p&gt;


	&lt;p&gt;Zur Plugininstallation klont man das github-repo:&lt;/p&gt;


&lt;pre&gt;git clone git://github.com/astashov/vim-ruby-debugger.git&lt;/pre&gt;

	&lt;p&gt;und kopiert dann einige Dateien in vims Pluginverzeichnis:&lt;/p&gt;


&lt;pre&gt;&amp;gt; cd ./vim-ruby-debugger
&amp;gt; cp -r vim/* ~/.vim/plugin/&lt;/pre&gt;

	&lt;p&gt;Im Hilfetext des Plugins in vim stehen deutliche mehr Informationen, als auf der Hauptseite des github-Projekts:&lt;/p&gt;


&lt;pre&gt;:helptags ~/.vim/doc
:help ruby-debugger&lt;/pre&gt;

	&lt;p&gt;Entgegen der Voreinstellung habe ich mir die Tastenkürzel auf die Alt-Taste verlegt. In der ~/.vimrc:&lt;/p&gt;


&lt;pre&gt;map &amp;lt;A-b&amp;gt;  :call g:RubyDebugger.toggle_breakpoint()&amp;lt;CR&amp;gt;
map &amp;lt;A-v&amp;gt;  :call g:RubyDebugger.open_variables()&amp;lt;CR&amp;gt;
map &amp;lt;A-m&amp;gt;  :call g:RubyDebugger.open_breakpoints()&amp;lt;CR&amp;gt;
map &amp;lt;A-s&amp;gt;  :call g:RubyDebugger.step()&amp;lt;CR&amp;gt;
map &amp;lt;A-n&amp;gt;  :call g:RubyDebugger.next()&amp;lt;CR&amp;gt;
map &amp;lt;A-c&amp;gt;  :call g:RubyDebugger.continue()&amp;lt;CR&amp;gt;
map &amp;lt;A-e&amp;gt;  :call g:RubyDebugger.exit()&amp;lt;CR&amp;gt;
map &amp;lt;A-d&amp;gt;  :call g:RubyDebugger.remove_breakpoints()&amp;lt;CR&amp;gt;

let g:ruby_debugger_fast_sender = 1&lt;/pre&gt;

	&lt;p&gt;Die Letzte Zeile ist nötig, um die Benutzung eines Socket-Scripts in C zu aktivieren, dass vermutlich etwas schneller ist, als der übliche Weg (siehe Hilfetext).&lt;/p&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;p&gt;&lt;a href=&quot;http://github.com/astashov/vim-ruby-debugger/tree/master&quot;&gt;github.com/astashov/vim-ruby-debugger&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-29:252</id>
    <published>2009-05-29T11:55:00Z</published>
    <updated>2009-05-29T12:07:48Z</updated>
    <category term="Gems"/>
    <category term="Misc"/>
    <category term="Testing"/>
    <category term="integrity"/>
    <category term="rack"/>
    <category term="sinatra"/>
    <category term="thin"/>
    <link href="http://rnotes.bluemars.net/252" rel="alternate" type="text/html"/>
    <title>integrity 0.1.10 + rack 1.0.0 + thin 1.2.2 + sinatra 0.9.1.3</title>
<content type="html">
            &lt;p&gt;Ich hoffe, dass sich die Aktualität dieses Artikels bald erledigt:
kurz gefasst, die aktuelle gem-Version von Thin basiert auf rack 1.0.0, die aktuelle integrity-Version auf sinatra 1.9.1.1, welches selbst rack 0.9.x benötigt.
Wenn man rack oder Thin oder beide updated, entstehen ein paar Probleme.&lt;/p&gt;


	&lt;p&gt;Dies ist &#8211; soweit ich es jetzt noch zusammenbekomme &#8211; wie ich auf meinem Ubuntu-Testserver eine (vermutlich) lauffähige Version zusammengefrickelt habe:&lt;/p&gt;


	&lt;h4&gt;Eine sinatra-Version von SR (s.u.) clonen&lt;/h4&gt;


	&lt;p&gt;Von http://github.com/sr/sinatra/tree/layout-local das git://github.com/sr/sinatra.git clonen und den branch &lt;em&gt;layout-local&lt;/em&gt; auschecken:&lt;/p&gt;


&lt;pre&gt;&amp;gt; git checkout -b layout-local
&amp;gt; vi lib/sinatra/base.rb&lt;/pre&gt;

	&lt;p&gt;dort musste ich für mein &lt;span class=&quot;caps&quot;&gt;REE&lt;/span&gt;-1.8.6&#8230; die Zeile #46:
  &lt;pre&gt;inject(0) { |len, part| len + part.bytesize }.to_s&lt;/pre&gt;
gegen
  &lt;pre&gt;inject(0) { |len, part| len + part.length }.to_s&lt;/pre&gt;
ersetzen. Das ist natürlich nicht das Gleiche &#8230;&lt;/p&gt;


	&lt;p&gt;Anschließend noch ein&lt;/p&gt;


&lt;pre&gt;&amp;gt; rake install&lt;/pre&gt;

	&lt;h4&gt;Die letzte integrity-Version clonen&lt;/h4&gt;


	&lt;p&gt;Von http://github.com/integrity/integrity/tree/master den git://github.com/integrity/integrity.git clonen:&lt;/p&gt;


&lt;pre&gt;&amp;gt; git clone git://github.com/integrity/integrity.git
&amp;gt; cd integrity
&amp;gt; vi integrity.gemspec  # 0.9.1.1 &amp;gt; 0.9.1.3
&amp;gt; gem uninstall integrity
&amp;gt; gem build integrity.gemspec 
&amp;gt; gem install integrity-0.1.10.gem&lt;/pre&gt;

	&lt;p&gt;In der .gemspec muss die Abhängigkeit auf die Version 0.9.1.3 gesetzt werden, damit integrity auch die aktuelle sinatra-Version aufruft.&lt;/p&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://irclogger.com/integrity/2009-05-19&quot;&gt;irclogger.com/integrity/2009-05-19&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/integrity/integrity/tree/master&quot;&gt;github.com/integrity/integrity/tree/master&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/sr/sinatra/tree/layout-local&quot;&gt;github.com/sr/sinatra/tree/layout-local&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://integrityapp.com/&quot;&gt;http://integrityapp.com/&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-26:251</id>
    <published>2009-05-26T12:59:00Z</published>
    <updated>2009-05-26T13:23:10Z</updated>
    <category term="JScript"/>
    <category term="Testing"/>
    <category term="jquery"/>
    <category term="multiple"/>
    <category term="select"/>
    <category term="selenium"/>
    <link href="http://rnotes.bluemars.net/251" rel="alternate" type="text/html"/>
    <title>die Qual der Wahl mit Selenium</title>
<content type="html">
            &lt;p&gt;Wie bringe ich meinem Integrationstest &#8211; also hier letztlich Selenium &#8211; bei, mehrere Optionen eines Multiselect-Feldes auszuwählen? Die vom &lt;em&gt;SeleniumDriver&lt;/em&gt; angebotene Methode &lt;em&gt;select&lt;/em&gt; sieht so aus:&lt;/p&gt;


&lt;pre&gt;select(selectLocator,optionLocator)&lt;/pre&gt;

	&lt;p&gt;wobei der &lt;em&gt;optionLocator&lt;/em&gt; soweit ich es sehe nur eine(1) Option zulässt. Das mehrmalige Aufrufen nacheinander klappt leider auch nicht, weil die vorher angewählte Option beim neuen Schritt wieder deaktiviert wird.&lt;/p&gt;


	&lt;p&gt;Dazu ist mir nur eingefallen, den Wert mit JavaScript zu setzen. Hier benutze ich jQuery, weil es in der Website eh benutzt wird. Mit &#8220;run_script&#8221; lassen sich Skripte unter dem Driver ausführen. In einer Cucumber-Stepsdefinition sieht das dann so aus:&lt;/p&gt;


&lt;pre&gt;Given /^I choose &quot;([^\&quot;]*)&quot; and &quot;([^\&quot;]*)&quot; from &quot;([^\&quot;]*)&quot;$/ do |opt1, opt2, field|
  selenium.run_script(&quot;$('##{field}').val(['#{opt1}','#{opt2}'])&quot;)
end&lt;/pre&gt;

	&lt;p&gt;Der &lt;em&gt;val&lt;/em&gt;-Methode von jQuery kann man ein Wertearray übergeben.&lt;/p&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://selenium.rubyforge.org/rdoc/classes/Selenium/SeleniumDriver.html&quot;&gt;selenium.rubyforge.org/rdoc/classes/Selenium&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://myphpetc.blogspot.com/2009/03/jquery-select-elements-tips-and-tricks.html&quot;&gt;jquery-select-elements-tips-and-tricks&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-25:250</id>
    <published>2009-05-25T17:53:00Z</published>
    <updated>2009-05-25T20:40:11Z</updated>
    <category term="Ruby"/>
    <category term="and"/>
    <category term="assignment"/>
    <category term="operator"/>
    <link href="http://rnotes.bluemars.net/250" rel="alternate" type="text/html"/>
    <title>Gotcha: die Klebrigkeit von Operatoren</title>
<content type="html">
            &lt;p&gt;Einmal mehr&#8230;&lt;/p&gt;


	&lt;p&gt;dies&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;...select {|group| ( my_rolls.include? group.responsible_id ) &amp;amp;&amp;amp; blah.true? }&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;ist &lt;span class=&quot;caps&quot;&gt;NICHT&lt;/span&gt; das Gleiche wie dies:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;...select {|group| my_rolls.include? group.responsible_id &amp;amp;&amp;amp; blah.true? }&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;argh.&lt;/p&gt;


	&lt;p&gt;Hier liegt das Problem:&lt;/p&gt;


&lt;pre&gt;&amp;gt;&amp;gt; [1,2,3].include? 2 &#38;&#38; true
=&amp;gt; false&lt;/pre&gt;

	&lt;p&gt;Klammern machen einen schlanken Fuß:&lt;/p&gt;


&lt;pre&gt;&amp;gt;&amp;gt; [1,2,3].include?(2) &#38;&#38; true
=&amp;gt; true&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-22:249</id>
    <published>2009-05-22T13:00:00Z</published>
    <updated>2009-05-22T13:15:30Z</updated>
    <category term="Misc"/>
    <category term="Rails"/>
    <category term="asynchron"/>
    <category term="daemon"/>
    <category term="pdftotext"/>
    <category term="timeout"/>
    <link href="http://rnotes.bluemars.net/249" rel="alternate" type="text/html"/>
    <title>Hintergrunddienste ordentlich versorgen</title>
<content type="html">
            &lt;p&gt;Für Railsprozesse, die im Hintergrund asynchron Dinge erledigen sollen, sind ein paar Dinge ganz hilfreich:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Subroutinen zeitlich zu begrenzen und ggf. auftretende Fehler abzufangen&lt;/li&gt;
		&lt;li&gt;den Dienst selbst auf Steuersignale horchen zu lassen (hier Sig-Term)&lt;/li&gt;
		&lt;li&gt;adäquate Logeinträge zu prodizieren.&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Der folgende Schnipsel zeigt an einer Pdf-Konvertierung, wie man&#8217;s machen kann. Er kann als Daemon (in Zusammenhang mit dem &lt;em&gt;daemons&lt;/em&gt;-gem) gestartet werden:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env ruby&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;c&quot;&gt;# You might want to change this&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;ENV&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;RAILS_ENV&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;] ||= &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;production&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.dirname(&lt;span class=&quot;pc&quot;&gt;__FILE__&lt;/span&gt;) + &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;/../../config/environment&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;gv&quot;&gt;$running&lt;/span&gt; = &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;Signal&lt;/span&gt;.trap(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;TERM&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;gv&quot;&gt;$running&lt;/span&gt; = &lt;span class=&quot;pc&quot;&gt;false&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;while&lt;/span&gt;(&lt;span class=&quot;gv&quot;&gt;$running&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;tt&gt;
&lt;/tt&gt;  pdfs = &lt;span class=&quot;co&quot;&gt;QAttachment&lt;/span&gt;.all.select {|qa| qa.content_type == &lt;tt&gt;
&lt;/tt&gt;           &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;application/pdf&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &amp;amp;&amp;amp; qa.answer.andand.value_str.blank?}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  pdfs.each &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |f| &lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.readable?(f.public_filename)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        timeout(&lt;span class=&quot;i&quot;&gt;60&lt;/span&gt;) &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;          f.answer.value_str = &lt;span class=&quot;sh&quot;&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;pdftotext -enc UTF-8 -q &amp;quot;&lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;f.public_filename&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;&amp;quot; -&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        f.answer.value_str = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;PDF-ERROR&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; f.answer.value_str.blank?&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;rescue&lt;/span&gt; &lt;span class=&quot;co&quot;&gt;Timeout&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Error&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        f.answer.value_str = &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;PDF-ERROR&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      f.answer.save&lt;tt&gt;
&lt;/tt&gt;      &lt;span class=&quot;co&quot;&gt;ActiveRecord&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Base&lt;/span&gt;.logger.info &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;Pdf-Conversion failed for Attachment&lt;tt&gt;
&lt;/tt&gt;          &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;f.answer.id&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; at &lt;/span&gt;&lt;span class=&quot;il&quot;&gt;&lt;span class=&quot;idl&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now&lt;span class=&quot;idl&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;if&lt;/span&gt; f.answer.value_str == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;PDF-ERROR&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;else&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      f.destroy&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  sleep &lt;span class=&quot;i&quot;&gt;10&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-21:248</id>
    <published>2009-05-21T14:58:00Z</published>
    <updated>2009-05-21T16:17:35Z</updated>
    <category term="Misc"/>
    <category term="Testing"/>
    <category term="firefox"/>
    <category term="network-manager"/>
    <category term="offline"/>
    <category term="selenium"/>
    <link href="http://rnotes.bluemars.net/248" rel="alternate" type="text/html"/>
    <title>Gotcha: Selenium-Tests ohne Netzwerk</title>
<content type="html">
            &lt;p&gt;Wenn ich mein Ubuntu-Laptop so ganz ohne Netzwerkverbindung starte &#8211; kein &lt;span class=&quot;caps&quot;&gt;LAN&lt;/span&gt;/WAN, entsteht ein nerviges Phänomen: der Firefox, der von Selenium bei einem Integrationstest gestartet wird, hält sich für schlau und startet im Offline-Modus.&lt;/p&gt;


	&lt;p&gt;Kein Problem, würde man denken: es wird ja eh nur auf der 127.0.0.1 getestet. Ha! Auch lokale Seiten lassen sich nicht aufrufen und ergo meldet Selenium einen Sessionfehler.&lt;/p&gt;


	&lt;p&gt;Das Anlegen von dummy-Gateways, &lt;span class=&quot;caps&quot;&gt;DNS&lt;/span&gt;-Servern etc. hat da nichts gebracht (wie kriegt der Browser eigentlich raus, dass kein &lt;span class=&quot;caps&quot;&gt;WAN&lt;/span&gt; da ist?). Aber: wenn man den &lt;em&gt;NetworkManager&lt;/em&gt; beendet, ist auf einmal alles gut:&lt;/p&gt;


&lt;pre&gt;sudo /etc/init.d/NetworkManager stop&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-12:247</id>
    <published>2009-05-12T14:00:00Z</published>
    <updated>2009-05-12T14:01:44Z</updated>
    <category term="Gems"/>
    <category term="Rails"/>
    <category term="Testing"/>
    <category term="debugger"/>
    <category term="osx"/>
    <category term="ruby-debug"/>
    <category term="selenium"/>
    <link href="http://rnotes.bluemars.net/247" rel="alternate" type="text/html"/>
    <title>Selenium, der ruby-Debugger und OsX</title>
<content type="html">
            &lt;p&gt;Die Kombination cucumber/webrat/Selenium macht mir viel Spaß! Es ist sogar möglich während einer Selenium-Sitzung den ruby-debugger zu starten und mit dem Browser zu interagieren. Auf einer Ubuntu-Maschine könnte man folgende Steps definieren:&lt;/p&gt;


&lt;pre&gt;Given I follow the link &quot;id=vorgangslink&quot; 
And I follow the link &quot;id=p2show&quot; 
And I follow the link &quot;id=formlink_1&quot; 
And I type &quot;ein&quot; into &quot;id=answer_7&quot; 
And I wait 1 second
And the debugger is started
Then I should see &quot;ein String&quot;&lt;/pre&gt;

	&lt;p&gt;Wobei der Debugger dann so aufgerufen wird:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^the debugger is started$&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  debugger &lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Im konkreten Lauf klappt das prima. Wenn man das Gleiche unter OsX tut, wirft das System einem allerdings eine Fehlermeldung um die Ohren, wenn man das &lt;em&gt;selenium&lt;/em&gt;-Objekt anspricht, um den Browser zu steuern:&lt;/p&gt;


&lt;pre&gt;    Given I follow the link &quot;id=vorgangslink&quot; 
    And I follow the link &quot;id=p2show&quot; 
    And I follow the link &quot;id=formlink_1&quot; 
    And I type &quot;ein&quot; into &quot;id=answer_7&quot; 
    And I wait 1 second
/opt/local/lib/ruby/gems/1.8/gems/cucumber-0.3.3/lib/cucumber/ast/step_invocation.rb:33
status!(:passed)

(rdb:1) selenium.type_keys(&quot;id=answer_7&quot;, &quot;hey&quot;)
NameError Exception: undefined local variable or method `selenium' for #&amp;lt;Cucumber::Ast::StepInvocation:0x36c9f28&amp;gt;

(rdb:1) list
[28, 37] in /opt/local/lib/ruby/gems/1.8/gems/cucumber-0.3.3/bin/...
   28          unless @skip_invoke || options[:dry_run] || exception ...
   29            @skip_invoke = true
   30            begin
...

(rdb:1)&lt;/pre&gt;

	&lt;p&gt;Der Grund liegt darin, dass der OsX-Debugger im Gegensatz zu Linux am Ende eines Blockes bereits in den umliegenden Kontext wechselt, und damit das &lt;em&gt;selenium&lt;/em&gt;-Objekt vergisst. Sorgt man durch Anfügen eines nichtstuenden Ausdrucks (hier &lt;em&gt;true&lt;/em&gt;) dafür, das das &lt;em&gt;debugger&lt;/em&gt;-Kommando nicht das letztze im Block ist, ist alles gut:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;co&quot;&gt;Given&lt;/span&gt; &lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^the debugger is started$&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  debugger &lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;pc&quot;&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-10:246</id>
    <published>2009-05-10T18:20:00Z</published>
    <updated>2009-05-10T18:24:44Z</updated>
    <category term="Gems"/>
    <category term="Misc"/>
    <category term="utf8"/>
    <category term="ya2yaml"/>
    <category term="yaml"/>
    <link href="http://rnotes.bluemars.net/246" rel="alternate" type="text/html"/>
    <title>YAML-Files mit UTF-8-Encoding schreiben</title>
<content type="html">
            &lt;p&gt;Einmal monatlich möchte(!) ich die Liste aller abgehakten Todos aus der &lt;a href=&quot;http://www.getontracks.org/&quot;&gt;Tracks&lt;/a&gt; &#8211; Todoliste in unser Zeit-Buchungssystem übertragen. Der kürzeste Weg (es hat keine Web-API) besteht, soweit ich es sehe darin, die einzelnen Tasks nach Datum und Bereich zu gruppieren und als &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt;-Datei auszugeben. Der Rest ist Copy-Paste. Leider unterstützt die gewöhnliche &#8221;.to_yaml&#8221;-Methode das &lt;span class=&quot;caps&quot;&gt;UTF&lt;/span&gt;-8 nur unzulänglich:&lt;/p&gt;


&lt;pre&gt;&amp;gt;&amp;gt; puts &quot;Wühlmaus&quot;.to_yaml
--- &quot;W\xC3\xBChlmaus&quot;&lt;/pre&gt;

	&lt;p&gt;Das &lt;em&gt;ya2yaml&lt;/em&gt;-gem schafft Abhilfe:&lt;/p&gt;


&lt;pre&gt;&amp;gt;&amp;gt; require 'ya2yaml';

&amp;gt;&amp;gt; puts &quot;Wühlmaus&quot;.ya2yaml
--- Wühlmaus
&lt;/pre&gt;

	&lt;p&gt;Jetzt klappt auch der Export:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;c&quot;&gt;#!/usr/bin/env /var/www/tracks/script/runner&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;ya2yaml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;puts &lt;span class=&quot;co&quot;&gt;Project&lt;/span&gt;.find_by_name(&lt;span class=&quot;pc&quot;&gt;ARGV&lt;/span&gt;[&lt;span class=&quot;i&quot;&gt;0&lt;/span&gt;]).todos(&lt;span class=&quot;sy&quot;&gt;:oder&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;completed_at ASC&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;).select {|t| &lt;tt&gt;
&lt;/tt&gt;      t.state == &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;completed&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;}.group_by {|t| t.completed_at.to_s[&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^2009-([^ ]+) .+$&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;]}.&lt;tt&gt;
&lt;/tt&gt;      map {|k,v| {k =&amp;gt; v.group_by {|t| t.context.name }.map {|l,m| {l =&amp;gt; m.map{|o| &lt;tt&gt;
&lt;/tt&gt;      [o.description, o.notes].join(&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; | &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)[&lt;span class=&quot;rx&quot;&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;^(.+?)( &lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;\|&lt;/span&gt;&lt;span class=&quot;k&quot;&gt; )?$&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;/&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;i&quot;&gt;1&lt;/span&gt;].strip}}}}}.ya2yaml&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;pre&gt;/var/www/tracks(master) &amp;gt; ./bcs.rb &quot;2009-04&quot; 
--- 
- 
  04-07: 
    - 
      ? &quot;Admin. Infrastruktur&quot; 
      : 
        - Übertragen Fileserverkonf. nach TM
    - 
      Customer-Service:
      ...&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-05-02:244</id>
    <published>2009-05-02T15:45:00Z</published>
    <updated>2009-05-02T15:45:26Z</updated>
    <category term="Gems"/>
    <category term="JScript"/>
    <category term="Plugins"/>
    <category term="Rails"/>
    <category term="api"/>
    <category term="flot"/>
    <category term="garb"/>
    <category term="google_analytics"/>
    <category term="jquery"/>
    <link href="http://rnotes.bluemars.net/244" rel="alternate" type="text/html"/>
    <title>Die Google-Analytics API spricht mit dir</title>
<content type="html">
            &lt;p&gt;Kurz nach der Veröffentlichung der neuen Google-Analytics-API gibt es jetzt das gem &lt;em&gt;garb&lt;/em&gt;, welches die Kommunikation damit erheblich vereinfacht. In diesem Beispiel frage ich die Werte &lt;em&gt;visits&lt;/em&gt;, &lt;em&gt;pageviews&lt;/em&gt;, etc. für den letzten Monat ab und übergebe sie dem jQuery-Plugin &lt;em&gt;flot&lt;/em&gt;, das diese Daten auf eine recht hübsche interaktive Weise darstellt:&lt;/p&gt;


	&lt;p&gt;&lt;/p&gt;


	&lt;p&gt;Hier folgen die Ergänzungen zu einer leeren Rails-2.3.2-Instanz. Das gesamte Projekt habe ich zum Clonen und Spielen auf Github eingestellt (s.u.).&lt;/p&gt;


	&lt;h4&gt;Die Umgebung&lt;/h4&gt;


	&lt;p&gt;Das gem wird aufgerufen (&amp;gt; 0.2), aus einem &lt;span class=&quot;caps&quot;&gt;YAML&lt;/span&gt;-File werden die Accountinformationen eingelesen und eine Session mit Google etabliert.&lt;/p&gt;


	&lt;p&gt;In config/environment.rb:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;...&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;Rails&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Initializer&lt;/span&gt;.run &lt;span class=&quot;r&quot;&gt;do&lt;/span&gt; |config|&lt;tt&gt;
&lt;/tt&gt;...&lt;tt&gt;
&lt;/tt&gt;  config.gem &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;vigetlabs-garb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:lib&lt;/span&gt; =&amp;gt; &lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;garb&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;...&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;google_path = &lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.join(&lt;span class=&quot;co&quot;&gt;RAILS_ROOT&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;config&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;google.yml&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;cv&quot;&gt;@@google_config&lt;/span&gt; = &lt;span class=&quot;co&quot;&gt;YAML&lt;/span&gt;.load(&lt;span class=&quot;co&quot;&gt;File&lt;/span&gt;.read(google_path))[&lt;span class=&quot;co&quot;&gt;RAILS_ENV&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;co&quot;&gt;Garb&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Session&lt;/span&gt;.login(&lt;span class=&quot;cv&quot;&gt;@@google_config&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;], &lt;span class=&quot;cv&quot;&gt;@@google_config&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;])&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;h4&gt;Anmeldedaten&lt;/h4&gt;


	&lt;p&gt;Das File config/google.yml enthält die Domaindaten:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;development:&lt;tt&gt;
&lt;/tt&gt;  domain: rnotes.bm.net&lt;tt&gt;
&lt;/tt&gt;  login: me@bm.net&lt;tt&gt;
&lt;/tt&gt;  password: p4ssw0rd&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;production:&lt;tt&gt;
&lt;/tt&gt;  domain: rnotes.bm.net&lt;tt&gt;
&lt;/tt&gt;  login: me@bm.net&lt;tt&gt;
&lt;/tt&gt;  password: p4ssw0rd&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;h4&gt;Controller-Code&lt;/h4&gt;


	&lt;p&gt;Wenn der Welcome-Index aufgerufen wird, wird die Datenabfrage im Controller assembliert und aufgerufen. Einer sauberen &lt;span class=&quot;caps&quot;&gt;MVC&lt;/span&gt;-Kultur folgend, sollte man dies in einem richtigen Projekt vielleicht in ein Modell geben.&lt;/p&gt;


	&lt;p&gt;app/controllers/welcome_controller.rb:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;r&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;cl&quot;&gt;WelcomeController&lt;/span&gt; &amp;lt; &lt;span class=&quot;co&quot;&gt;ApplicationController&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;fu&quot;&gt;index&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    profile = &lt;span class=&quot;co&quot;&gt;Garb&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Profile&lt;/span&gt;.all.select {|p| p.title == &lt;tt&gt;
&lt;/tt&gt;                              &lt;span class=&quot;cv&quot;&gt;@@google_config&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]}.first&lt;tt&gt;
&lt;/tt&gt;    report = &lt;span class=&quot;co&quot;&gt;Garb&lt;/span&gt;::&lt;span class=&quot;co&quot;&gt;Report&lt;/span&gt;.new(profile, &lt;span class=&quot;sy&quot;&gt;:start_date&lt;/span&gt; =&amp;gt; &lt;tt&gt;
&lt;/tt&gt;                              &lt;span class=&quot;i&quot;&gt;4&lt;/span&gt;.weeks.ago, &lt;span class=&quot;sy&quot;&gt;:end_date&lt;/span&gt; =&amp;gt; &lt;span class=&quot;co&quot;&gt;Time&lt;/span&gt;.now )&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    report.metrics &lt;span class=&quot;sy&quot;&gt;:pageviews&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:visits&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:visitors&lt;/span&gt;, &lt;span class=&quot;sy&quot;&gt;:new_visits&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    report.dimensions &lt;span class=&quot;sy&quot;&gt;:date&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    report.sort &lt;span class=&quot;sy&quot;&gt;:date&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    result = report.results&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@visitors&lt;/span&gt; = result.map(&amp;amp;&lt;span class=&quot;sy&quot;&gt;:visitors&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@visits&lt;/span&gt; = result.map(&amp;amp;&lt;span class=&quot;sy&quot;&gt;:visits&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@newvisits&lt;/span&gt; = result.map(&amp;amp;&lt;span class=&quot;sy&quot;&gt;:new_visits&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@pageviews&lt;/span&gt; = result.map(&amp;amp;&lt;span class=&quot;sy&quot;&gt;:pageviews&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@dates&lt;/span&gt; = result.map {|d| d.date.to_time.to_i * &lt;span class=&quot;i&quot;&gt;1000&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;    &lt;span class=&quot;iv&quot;&gt;@domain&lt;/span&gt; = &lt;span class=&quot;cv&quot;&gt;@@google_config&lt;/span&gt;[&lt;span class=&quot;s&quot;&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;domain&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;/span&gt;]&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class=&quot;r&quot;&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Hier ist bemerkenswert, wie die Datumsformate &#8220;CCYYMMDD&#8221;, die von Google als String kommen in Javascript-Timestamps umgerechnet werden, wie &lt;em&gt;flot&lt;/em&gt; sie erwartet.&lt;/p&gt;


	&lt;h4&gt;Die Diagrammdarstellung&lt;/h4&gt;


	&lt;p&gt;Im Index werden die Ergebnisse ein ein Javascript eingefügt, das letztlich &lt;em&gt;flot&lt;/em&gt; benutzt. Weitere Beispiele mit verschiedenen Optionen findet man auf der Website des Plugins.&lt;/p&gt;


	&lt;p&gt;Das app/views/welcome/index.html.erb-File:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;5&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;15&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;25&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;35&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;45&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;49&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;50&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;51&lt;tt&gt;
&lt;/tt&gt;52&lt;tt&gt;
&lt;/tt&gt;53&lt;tt&gt;
&lt;/tt&gt;54&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;55&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;56&lt;tt&gt;
&lt;/tt&gt;57&lt;tt&gt;
&lt;/tt&gt;58&lt;tt&gt;
&lt;/tt&gt;59&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;61&lt;tt&gt;
&lt;/tt&gt;62&lt;tt&gt;
&lt;/tt&gt;63&lt;tt&gt;
&lt;/tt&gt;64&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;65&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;66&lt;tt&gt;
&lt;/tt&gt;67&lt;tt&gt;
&lt;/tt&gt;68&lt;tt&gt;
&lt;/tt&gt;69&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;70&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;71&lt;tt&gt;
&lt;/tt&gt;72&lt;tt&gt;
&lt;/tt&gt;73&lt;tt&gt;
&lt;/tt&gt;74&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;75&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&amp;lt;h1&amp;gt;&amp;lt;%= @domain -%&amp;gt;&amp;lt;/h1&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;p&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/p&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;div id=&amp;quot;placeholder&amp;quot; style=&amp;quot;width:600px;height:300px&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;div id=&amp;quot;overview&amp;quot; style=&amp;quot;margin-left:200px;margin-top:20px;&lt;tt&gt;
&lt;/tt&gt;                                           width:400px;height:50px&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;script id=&amp;quot;source&amp;quot; language=&amp;quot;javascript&amp;quot; type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;tt&gt;
&lt;/tt&gt;$(function () {&lt;tt&gt;
&lt;/tt&gt;    var d1 = [&amp;lt;%= i = -1; @visitors.map {|v| i += 1; &lt;tt&gt;
&lt;/tt&gt;                        &amp;quot;[#{@dates[i]}, #{v}]&amp;quot; }.join(&amp;quot;, &amp;quot;) -%&amp;gt;];&lt;tt&gt;
&lt;/tt&gt;    var d2 = [&amp;lt;%= i = -1; @visits.map {|v| i += 1; &lt;tt&gt;
&lt;/tt&gt;                        &amp;quot;[#{@dates[i]}, #{v}]&amp;quot; }.join(&amp;quot;, &amp;quot;) -%&amp;gt;];&lt;tt&gt;
&lt;/tt&gt;    var d3 = [&amp;lt;%= i = -1; @pageviews.map {|v| i += 1; &lt;tt&gt;
&lt;/tt&gt;                        &amp;quot;[#{@dates[i]}, #{v}]&amp;quot; }.join(&amp;quot;, &amp;quot;) -%&amp;gt;];&lt;tt&gt;
&lt;/tt&gt;    var d4 = [&amp;lt;%= i = -1; @newvisits.map {|v| i += 1; &lt;tt&gt;
&lt;/tt&gt;                        &amp;quot;[#{@dates[i]}, #{v}]&amp;quot; }.join(&amp;quot;, &amp;quot;) -%&amp;gt;];&lt;tt&gt;
&lt;/tt&gt;    var d = [ { label: 'Visitors', data: d1 }, { label: 'Visits', data: d2 }, &lt;tt&gt;
&lt;/tt&gt;        { label: 'Pageviews', data: d3 },  { label: 'New visits', data: d4 } ];&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    // helper for returning the weekends in a period&lt;tt&gt;
&lt;/tt&gt;    function weekendAreas(axes) {&lt;tt&gt;
&lt;/tt&gt;        var markings = [];&lt;tt&gt;
&lt;/tt&gt;        var d = new Date(axes.xaxis.min);&lt;tt&gt;
&lt;/tt&gt;        // go to the first Saturday&lt;tt&gt;
&lt;/tt&gt;        d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 1) % 7))&lt;tt&gt;
&lt;/tt&gt;        d.setUTCSeconds(0);&lt;tt&gt;
&lt;/tt&gt;        d.setUTCMinutes(0);&lt;tt&gt;
&lt;/tt&gt;        d.setUTCHours(0);&lt;tt&gt;
&lt;/tt&gt;        var i = d.getTime();&lt;tt&gt;
&lt;/tt&gt;        do {&lt;tt&gt;
&lt;/tt&gt;            // when we don't set yaxis the rectangle automatically&lt;tt&gt;
&lt;/tt&gt;            // extends to infinity upwards and downwards&lt;tt&gt;
&lt;/tt&gt;            markings.push({ xaxis: { from: i, to: i + 2 * 24 * 60 * 60 * 1000 } });&lt;tt&gt;
&lt;/tt&gt;            i += 7 * 24 * 60 * 60 * 1000;&lt;tt&gt;
&lt;/tt&gt;        } while (i &amp;lt; axes.xaxis.max);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;        return markings;&lt;tt&gt;
&lt;/tt&gt;    }&lt;tt&gt;
&lt;/tt&gt;    &lt;tt&gt;
&lt;/tt&gt;    var options = {&lt;tt&gt;
&lt;/tt&gt;        xaxis: { mode: &amp;quot;time&amp;quot; },&lt;tt&gt;
&lt;/tt&gt;        selection: { mode: &amp;quot;x&amp;quot; },&lt;tt&gt;
&lt;/tt&gt;        legend: { position: 'sw' },&lt;tt&gt;
&lt;/tt&gt;        points: { show: true },&lt;tt&gt;
&lt;/tt&gt;        lines: { show: true },&lt;tt&gt;
&lt;/tt&gt;        grid: { markings: weekendAreas }&lt;tt&gt;
&lt;/tt&gt;    };&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    var plot = $.plot($(&amp;quot;#placeholder&amp;quot;), d, options);&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    var overview = $.plot($(&amp;quot;#overview&amp;quot;), [d1, d2, d3, d4], {&lt;tt&gt;
&lt;/tt&gt;        lines: { show: true, lineWidth: 1 },&lt;tt&gt;
&lt;/tt&gt;        shadowSize: 0,&lt;tt&gt;
&lt;/tt&gt;        xaxis: { ticks: [], mode: &amp;quot;time&amp;quot; },&lt;tt&gt;
&lt;/tt&gt;        selection: { mode: &amp;quot;x&amp;quot; }&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    $(&amp;quot;#placeholder&amp;quot;).bind(&amp;quot;plotselected&amp;quot;, function (event, ranges) {&lt;tt&gt;
&lt;/tt&gt;        // do the zooming&lt;tt&gt;
&lt;/tt&gt;        plot = $.plot($(&amp;quot;#placeholder&amp;quot;), d,&lt;tt&gt;
&lt;/tt&gt;                      $.extend(true, {}, options, {&lt;tt&gt;
&lt;/tt&gt;                          xaxis: { min: ranges.xaxis.from, max: ranges.xaxis.to }&lt;tt&gt;
&lt;/tt&gt;                      }));&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;        // don't fire event on the overview to prevent eternal loop&lt;tt&gt;
&lt;/tt&gt;        overview.setSelection(ranges, true);&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;    $(&amp;quot;#overview&amp;quot;).bind(&amp;quot;plotselected&amp;quot;, function (event, ranges) {&lt;tt&gt;
&lt;/tt&gt;        plot.setSelection(ranges);&lt;tt&gt;
&lt;/tt&gt;    });&lt;tt&gt;
&lt;/tt&gt;});&lt;tt&gt;
&lt;/tt&gt;&amp;lt;/script&amp;gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;h4&gt;Javascripts und JRails&lt;/h4&gt;


	&lt;p&gt;&lt;em&gt;flot&lt;/em&gt; selbst benötigt jQuery. Eine elegante und schnelle Art der Einbettung ist es, das jRails-plugin zu installieren &#8211; es bringt jQuery mit:&lt;/p&gt;


&lt;pre&gt;script/plugin install http://ennerchi.googlecode.com/svn/trunk/plugins/jrails&lt;/pre&gt;

	&lt;p&gt;Das fügt die rechten Files in public/javascripts ein. Es fehlt nur noch das &lt;em&gt;jquery.flot.js&lt;/em&gt;:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;jrails.js&lt;/li&gt;
		&lt;li&gt;jquery-ui.js&lt;/li&gt;
		&lt;li&gt;jquery.flot.js&lt;/li&gt;
		&lt;li&gt;jquery.js&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h4&gt;das html-Layout&lt;/h4&gt;


	&lt;p&gt;Zum Schluss müssen die Scripte im Layout aktivert werden &#8211; app/views/layouts/application.html.erb:&lt;/p&gt;


&lt;div class=&quot;CodeMacro&quot;&gt;
&lt;table class=&quot;CodeRay&quot;&gt;&lt;tr&gt;
  &lt;td title=&quot;click to toggle&quot; class=&quot;line_numbers&quot;&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class=&quot;code&quot;&gt;&lt;pre&gt;...&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;&amp;lt;%= javascript_include_tag :defaults %&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class=&quot;c&quot;&gt;&amp;lt;%= javascript_include_tag 'jquery.flot' %&amp;gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;...&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://github.com/fwoeck/analytics/tree/master&quot;&gt;github.com/fwoeck/analytics&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://www.viget.com/extend/introducing-garb-access-the-google-analytics-data-export-api-with-ruby#continue&quot;&gt;introducing-garb-access-the-google-analytics-data-export-api-with-ruby&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/vigetlabs/garb/tree/master&quot;&gt;github.com/vigetlabs/garb&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://code.google.com/p/flot/&quot;&gt;code.google.com/p/flot&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://code.google.com/intl/de-DE/apis/analytics/docs/gdata/gdataReferenceDimensionsMetrics.html&quot;&gt;code.google.com/gdataReferenceDimensionsMetrics&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
  <entry xml:base="http://rnotes.bluemars.net/">
    <author>
      <name>fwoeck</name>
    </author>
    <id>tag:rnotes.bluemars.net,2009-04-29:243</id>
    <published>2009-04-29T09:39:00Z</published>
    <updated>2009-04-29T09:41:14Z</updated>
    <category term="Plugins"/>
    <category term="Rails"/>
    <category term="debug"/>
    <category term="explain"/>
    <category term="middleware"/>
    <category term="rack"/>
    <link href="http://rnotes.bluemars.net/243" rel="alternate" type="text/html"/>
    <title>Sehr cooles Debug- und Analysetool: rack-bug</title>
<content type="html">
            &lt;p&gt;Die Rackifizierung greift um sich! Hier sehen wir eine Folge: Bryan Helmkamp hat grade sein an ein Django-Tool angelehntes &lt;em&gt;rack-bug&lt;/em&gt; vorgestellt. Es ist eine Rackmiddleware, die ein Statusfenster in die laufende Website einblendet. Es gibt eine Menge sehr interessanter Möglichkeiten, z.B. die Auswertung&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;der verbrauchten &lt;span class=&quot;caps&quot;&gt;CPU&lt;/span&gt;-Zeiten en Detail&lt;/li&gt;
		&lt;li&gt;der Session- und Cookievariablen&lt;/li&gt;
		&lt;li&gt;der &lt;span class=&quot;caps&quot;&gt;ENV&lt;/span&gt;- und Headerumgebung&lt;/li&gt;
		&lt;li&gt;der &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt;-Statements mit Backtrace, Explain, Timings und der Wiederholung einzelner Selects&lt;/li&gt;
		&lt;li&gt;der Cachinhalte&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;und mehr!&lt;/p&gt;


	&lt;h4&gt;Die Installation&lt;/h4&gt;


	&lt;p&gt;... ist trivial (hier für Rails):&lt;/p&gt;


&lt;pre&gt;script/plugin install git://github.com/brynary/rack-bug.git&lt;/pre&gt;

	&lt;p&gt;Anschließend ruft man die Middleware auf. In der &lt;em&gt;config/initializers/middleware.rb&lt;/em&gt;:&lt;/p&gt;


&lt;pre&gt;require &quot;rack/bug&quot; 

ActionController::Dispatcher.middleware.use Rack::Bug,
  :ip_masks   =&amp;gt; [IPAddr.new(&quot;127.0.0.1&quot;)],
  :secret_key =&amp;gt; &quot;KsdUrsfdY7sdfDEsdf52sdfhD4yWY+8z1&quot;,
  :password   =&amp;gt; &quot;p4ssw0rd&quot;&lt;/pre&gt;

	&lt;p&gt;Nun lässt sich das Tool auf der Unterseite &lt;code&gt;/__rack_bug__/bookmarklet.html&lt;/code&gt; des Projekts aktivieren.&lt;/p&gt;


	&lt;p&gt;&lt;/p&gt;


	&lt;h4&gt;Weblinks&lt;/h4&gt;


	&lt;ol&gt;
	&lt;li&gt;&lt;a href=&quot;http://www.brynary.com/2009/4/22/rack-bug-debugging-toolbar-in-four-minutes&quot;&gt;www.brynary.com/rack-bug-debugging-toolbar-in-four-minutes&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;&lt;a href=&quot;http://github.com/brynary/rack-bug/tree/master&quot;&gt;github.com/brynary/rack-bug&lt;/a&gt;&lt;/li&gt;
	&lt;/ol&gt;
          </content>  </entry>
</feed>
