<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de-DE">
  <title type="text">Ruby-Mine</title>
  <id>tag:www.ruby-mine.de,2012:/</id>
  
  <link href="http://www.ruby-mine.de/" rel="alternate" type="text/html" />
  <updated>2012-04-21T08:37:48Z</updated>
  <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ruby_mine" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="ruby_mine" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><subtitle type="html">deutschsprachiges Blog über die Programmiersprache Ruby</subtitle><entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>bovi</name>
    </author>
    <id>tag:www.ruby-mine.de,2012-04-20:12704</id>
    <published>2012-04-20T18:32:00Z</published>
    <updated>2012-04-21T08:37:48Z</updated>
    <category term="Allgemeines" />
    <category term="bovi [Autor]" />
    <link href="http://www.ruby-mine.de/2012/4/20/mruby" rel="alternate" type="text/html" />
    <title>mruby</title>
<content type="html">
            &lt;p&gt;Das &lt;a href="https://github.com/mruby/mruby"&gt;mruby&lt;/a&gt; Repository wurde soeben auf Github geöffnet. Sofern es nicht bekannt sein sollte: mruby ist eine vollständige Neuimplementierung von Ruby mit dem Fokus auf Embedded-Systems, Mikrocontroller oder auch als Integration in vorhandene Applikationen (ähnlich zu Lua). Insofern sehr interessant da die Entwicklung von der japanischen Regierung gesponsert wurde und von matz angeführt wird.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>bovi</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-09-23:12400</id>
    <published>2011-09-23T15:47:00Z</published>
    <updated>2011-09-24T00:50:40Z</updated>
    <category term="bovi [Autor]" />
    <category term="skade [Autor]" />
    <category term="Veranstaltungen" />
    <link href="http://www.ruby-mine.de/2011/9/23/germany-rb-2011-review" rel="alternate" type="text/html" />
    <title>Germany.rb 2011 review</title>
<summary type="html">&lt;p&gt;Das war sie nun unsere &lt;a href="http://www.ruby-lang.org/de/news/2011/06/23/germany-rb-2011-in-leipzig/"&gt;zweite Iteration der Germany.rb&lt;/a&gt; am 20. und 21. August 2011. Es waren ca. 25 Leute da und es gab insgesamt 13 auf Video aufgezeichnete Vorträge. Hier eine kleine Zusammenfassung wie es ablief und wie es weitergehen könnte.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Das war sie nun unsere &lt;a href="http://www.ruby-lang.org/de/news/2011/06/23/germany-rb-2011-in-leipzig/"&gt;zweite Iteration der Germany.rb&lt;/a&gt; am 20. und 21. August 2011. Es waren ca. 25 Leute da und es gab insgesamt 13 auf Video aufgezeichnete Vorträge. Hier eine kleine Zusammenfassung wie es ablief und wie es weitergehen könnte.&lt;/p&gt;
&lt;h3&gt;Ort&lt;/h3&gt;

	&lt;p&gt;Wie auch letztes Jahr trafen wir uns wieder im &lt;a href="http://sublab.org/"&gt;sublab&lt;/a&gt; (ein &lt;a href="http://en.wikipedia.org/wiki/Hackerspace"&gt;Hackerspace&lt;/a&gt; in &lt;a href="http://www.openstreetmap.org/?lat=51.3405&amp;amp;lon=12.3747&amp;amp;zoom=14&amp;amp;layers=M"&gt;Leipzig&lt;/a&gt;). Positiv war die offene Atmosphäre, welche uns die Freiheit gab auch abseits der Vorträge in einer anderen Ecke zu diskutieren und zu hacken. Der bereitgestellte Internetanschluss gab uns weitere Freiheiten mit denen wir nichtmal gerechnet hatten. Unsere spendenbasierte Nutzung hatte laut Feedback der sublab Betreiber gut geklappt. Dabei hatten wir die Teilnehmer darum gebeten, eine kleine Spende nach eigener Wahl im sublab zu hinterlassen. Als Kontrapunkte wurde von Teilnehmern die Sanitäranlage und die Raumtemperatur erwähnt.&lt;/p&gt;


&lt;h3&gt;Sponsoren&lt;/h3&gt;

	&lt;p&gt;Überraschenderweise hatten sich zwei Sponsoren gefunden. Das &lt;a href="http://www.ifbbw.de/"&gt;ifbbw&lt;/a&gt; hat uns mit einer tollen Kameraausrüstung ausgestattet und &lt;a href="http://www.castaclip.com/"&gt;castaclip&lt;/a&gt; hat den Beamer bezahlt und für alle Teilnehmer Essen für beide Tage gesponsert.&lt;/p&gt;


	&lt;p&gt;Auch wenn nicht direkt als Sponsoring gedacht, haben wir uns am Samstag abend das Essen der im Sublab stattfindenden &lt;a href="http://wiki.sublab.org/veranstaltungen_und_projekte:phantomspeisung"&gt;Phantomspeisung&lt;/a&gt; schmecken lassen. Vielen Dank auch an diese Seite.&lt;/p&gt;


	&lt;p&gt;&lt;i&gt;An dieser Stelle ein grosses Dankeschön – im Namen der Teilnehmer, welche sich sehr über das Essen gefreut haben und im Namen vieler anonymer Internetnutzer, die sich die Vorträge im Nachhinein noch einmal als Video hier anschauen können.&lt;/i&gt;&lt;/p&gt;


&lt;h3&gt;:next&lt;/h3&gt;

	&lt;p&gt;Um eine nächste Inkarnation möglich zu machen, hatten wir nach Herkunftsort und Feedback gefragt. Es kamen Leute aus Leipzig (was wohl klar war), Berlin (die meisten), Kamen (NRW), Unna (NRW), Offenbach/Main und Beijing. Als Feedback gab es u.a. die folgenden konkreten Vorschläge:&lt;/p&gt;


&lt;ul&gt;
&lt;li&gt;Abends länger :D&lt;/li&gt;
&lt;li&gt;Pro: Hbf-Shuttle, “Kostenlosigkeit”, lecker Essen ;)&lt;br /&gt;Con: Sanitäre Anlagen, Raumtemperatur&lt;/li&gt;
&lt;li&gt;War zwar nicht da aber etwas zentraler wäre cool ;)&lt;/li&gt;
&lt;/ul&gt;

	&lt;p&gt;Nach einigen Diskussionen sind wir zu den folgenden Schlüsselelementen gelangt, welche die Zukunft der Germany.rb umrahmen sollen. Was wollen wir weiterhin erreichen und was wollen wir vermeiden:&lt;/p&gt;


&lt;ol&gt;
&lt;li&gt;Wir wollen keine bisher existierende Veranstaltung ersetzen. Weder wollen wir eine Konkurrenz zur EuRuKo aufbauen noch wollen wir den Platz einer deutschen Ruby Konferenz einnehmen.&lt;/li&gt;
&lt;li&gt;Wir wollen einen Ort für Leute bieten, die normalerweise keine Ruby Konferenzen besuchen. Sei es aus finanziellen oder organisatorischen Gründen.&lt;/li&gt;
&lt;li&gt;Wir sind zufrieden mit der derzeitigen Art und Anzahl der Vorträge und wollen dies so beibehalten.&lt;/li&gt;
&lt;li&gt;Wir wollen die Möglichkeit ausbauen, parallel oder nach dem Vortragsprogramm an Ideen zu hacken. Dazu wollen wir die Möglichkeiten der gemeinsamen Kollaboration ausbauen und den Teilnehmern die Möglichkeit bieten auch bis in die tiefe Nacht zusammen zu sitzen und an Ideen zu arbeiten. Das ganze soll also um ein Hackfest Attribut ausgebaut werden.&lt;/li&gt;
&lt;li&gt;Wir wollen den niedrigen Kostenfootprint beibehalten oder sogar noch weiter senken.&lt;/li&gt;
&lt;li&gt;Wir wollen mit der Teilnehmeranzahl nicht stetig wachsen. Die derzeitige Teilnehmeranzahl von weniger als 30 Leuten lässt sich leicht und kostengünstig unterbringen. In Zukunft müssen wir austesten bis zu welchem Limit dies weiterhin möglich ist. Sollte die Teilnehmerzahl steigen, würden wir lieber die Häufigkeit der Veranstaltung erhöhen anstatt Gebühren zu verlangen.&lt;/li&gt;
&lt;/ol&gt;

	&lt;p&gt;Da wir beim nächsten Mal nicht blind davon ausgehen können, das wir erneut das Glück haben so tolle Sponsoren zu finden, würden wir gerne nach weiteren Möglichkeiten forschen, die Veranstaltung in diesem Rahmen weiterzutreiben. Jeder ist dazu aufgerufen, Ideen zu äussern die es ermöglichen die nächste Germany.rb in diesem Rahmen weiterhin so zu organisieren.&lt;/p&gt;


&lt;h3&gt;Vorträge&lt;/h3&gt;

	&lt;p&gt;Hier nun ein Rundumschlag mit Details zu jedem einzelnen Vortrag.&lt;/p&gt;


&lt;h4&gt;“Intro” von &lt;a href="http://twitter.com/#!/argorak"&gt;Florian&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Eröffnungsrede von Florian mit einer Zusammenfassung der wichtigsten Eckdaten und einer groben Planung des Ablaufes.&lt;/p&gt;




&lt;h4&gt;“ruby-lang.org” mit allen Germany.rb Teilnehmern&lt;/h4&gt;

	&lt;p&gt;Eine kleine Einführung  in die unserer Meinung nach wichtigsten Online-Ressourcen von Ruby für die Ruby Einsteiger beim Treffen. Da viel Input vom Publikum gekommen ist, ist die Tonqualität rech sub-optimal. Sorry für das und das unstrukturierte Vorgehen.&lt;/p&gt;




&lt;h4&gt;“Treating Code As an Essay” von &lt;a href="http://twitter.com/#!/rbjl"&gt;Jan&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;&lt;a href="http://www.ruby-mine.de/assets/2011/9/11/ruby-syntax.pdf"&gt;Vortragsfolien&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Jan gab einen Einführungsvortrag in die Grundlagen von Ruby. Basierend auf dem Aufsatz von Matz “Treating Code As an Essay”.&lt;/p&gt;




&lt;h4&gt;“Wie arbeitet eigentlich RDoc” von &lt;a href="http://pegasus-alpha.eu/quintus"&gt;Marvin&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;&lt;a href="http://www.ruby-mine.de/assets/2011/9/3/RDoc.pdf"&gt;Vortragsfolien&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Marvin spricht über den internen Aufbau von RDoc, mit dem Ziel eigene Erweiterungen für diese Bibliothek zu schreiben.&lt;/p&gt;




&lt;h4&gt;“RDoc &lt;span class="caps"&gt;PDF&lt;/span&gt; Output” von &lt;a href="http://pegasus-alpha.eu/quintus"&gt;Marvin&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Vorstellung von Marvins RDoc Erweiterung &lt;a href="https://github.com/Quintus/Papyrus"&gt;Papyrus&lt;/a&gt;, mit der eine Generierung von &lt;span class="caps"&gt;PDF&lt;/span&gt; Dokumentation möglich ist.&lt;/p&gt;




&lt;h4&gt;“Redmine Fork ChiliProject” von &lt;a href="http://twitter.com/#!/thegcat"&gt;Felix&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Felix spricht über den &lt;a href="https://www.chiliproject.org/"&gt;Redmine Fork ChiliProject&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;“Vagrant” von &lt;a href="http://twitter.com/#!/bascht"&gt;Sebastian&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Sebastian spricht über &lt;a href="http://vagrantup.com/"&gt;Vagrant&lt;/a&gt;, ein Verwaltungsprogramm für Virtuelle Maschinen von &lt;a href="http://www.virtualbox.org/"&gt;Virtual Box&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;“Padrino” von &lt;a href="http://twitter.com/#!/argorak"&gt;Florian&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Florian spricht über das &lt;a href="http://www.padrinorb.com"&gt;Webframework Padrino&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;“Operations” von &lt;a href="http://twitter.com/#!/xylakant"&gt;Felix&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Felix spricht über den gesamten Deployment-Prozess von Webapplikationen und stellt die jeweiligen Alternativen vor.&lt;/p&gt;




&lt;h4&gt;“API Leipzig” von &lt;a href="https://twitter.com/#!/martin_LE"&gt;Martin&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Martin spricht über die Opendata Initiative &lt;a href="http://apileipzig.de"&gt;&lt;span class="caps"&gt;API&lt;/span&gt; Leipzig&lt;/a&gt;.&lt;/p&gt;




&lt;h4&gt;“Tweak your Ruby Console” von  &lt;a href="http://twitter.com/#!/rbjl"&gt;Jan&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;&lt;a href="http://www.ruby-mine.de/assets/2011/9/11/irbtools_ripl.pdf"&gt;Vortragsfolien&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Jan spricht über Möglichkeiten seine eigene Ruby Konsole zu erweitern respektiv zu optimieren.&lt;/p&gt;




&lt;h4&gt;“OMG, Modules!” von &lt;a href="http://twitter.com/#!/argorak"&gt;Florian&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Unser Metraprogramming Vortrag von Florian der allerlei Spielereien mit Modulen erklärt.&lt;/p&gt;




&lt;h4&gt;“CodeRay 1RC1” von &lt;a href="http://twitter.com/#!/murphy_karasu"&gt;Kornelius&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;&lt;a href="http://www.ruby-mine.de/assets/2011/9/4/CodeRay_1.0.pdf"&gt;Vortragsfolien&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Kornelius spricht über das baldige &lt;a href="http://coderay.rubychan.de/"&gt;CodeRay&lt;/a&gt; Release 1.0&lt;/p&gt;



          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>bovi</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-08-14:12162</id>
    <published>2011-08-14T14:04:00Z</published>
    <updated>2011-08-14T14:17:40Z</updated>
    <category term="bovi [Autor]" />
    <category term="Veranstaltungen" />
    <link href="http://www.ruby-mine.de/2011/8/14/rubykaigi-2011" rel="alternate" type="text/html" />
    <title>RubyKaigi 2011</title>
<summary type="html">&lt;p&gt;Vom 16 bis 19. Juli 2011 fand die 6. und letzte RubyKaigi in Tokyo statt. Dabei handelt es sich neben der RubyConf und EuRuKo um die wichtigste jährliche Ruby Konferenz.&lt;/p&gt;


	&lt;p&gt;Hier gibt es ein paar Notizen von den aus meiner Sicht interessantesten Vorträgen.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Vom 16 bis 19. Juli 2011 fand die 6. und letzte RubyKaigi in Tokyo statt. Dabei handelt es sich neben der RubyConf und EuRuKo um die wichtigste jährliche Ruby Konferenz.&lt;/p&gt;


	&lt;p&gt;Hier gibt es ein paar Notizen von den aus meiner Sicht interessantesten Vorträgen.&lt;/p&gt;
&lt;h4&gt;“Ruby ruined my Life” von &lt;a href="http://tenderlovemaking.com/"&gt;Aaron Patterson&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Die erste Keynote wurde von Aaron Patterson gehalten. Seines Zeichens Ruby- und Rails-Core Committer welcher bei AT&amp;T Interactive zur Open Source Pflege angestellt ist. In seiner Keynote verglich er die Entwickungsprozesse der Ruby und Rails Community und vertrat die Meinung, dass die beiden Teams sich gegenseitig befruchten könnten indem sie Gewohnheiten der anderen übernehmen würden. So z.B. die nicht fest zugeschriebene Verantwortlichkeiten des Railsteams, welche im Rubyteam stark den Fortschritt behindert. Oder das koordinierte Release Management von yugui welches innerhalb von Rails nicht dediziert von einer Person durchgeführt wird und deshalb oft auf der Strecke bleibt.&lt;/p&gt;




&lt;h4&gt;“Next version of Ruby 1.8 and 1.9” von CRuby Development Team&lt;/h4&gt;

	&lt;p&gt;Während der Q&amp;A Session mit den Core Entwicklern wurden die folgenden Punkte für die Zukunft der CRuby Entwicklung mitgeteilt:&lt;/p&gt;


	&lt;p&gt;Die nächste und letzte Version von Ruby 1.8.6 wird in etwa zwei Monaten erscheinen. Sie wird ausschließlich Fehlerbereinigungen enthalten. Der aktuelle Maintainer hat angekündigt danach seine Arbeit daran einzustellen.&lt;/p&gt;


	&lt;p&gt;Seit 1.9.3 gibt es mithilfe von private_const eine Konstante als private zu markieren.&lt;/p&gt;


	&lt;p&gt;Seit kurzem ist sorah_h neuer Ruby Committer. Seine erste Integrationsaufgabe war für 1.9.3 test/unit zu parallelisieren.&lt;/p&gt;


	&lt;p&gt;Es wurden Anpassungen am &lt;span class="caps"&gt;GVL&lt;/span&gt; vorgenommen um Aktivitäten um diesen herum zu beschleunigen.&lt;/p&gt;


	&lt;p&gt;Koichi stellte eine Änderung am Thread Timer vor. Dieser verhält sich nun etwas intelligenter. U.a. deaktiviert er sich beim nicht Vorhandensein von multiplen Threads. Dies sorgt dafür das die kontinuierliche Prozessorlast von Ruby sinkt, da das permanente Scheduling alle 10ms in vielen Fällen wegfällt.&lt;/p&gt;


	&lt;p&gt;Ruby 1.9.3 wird nach aktuellem Plan Ende August veröffentlicht. Eine erste Preview steht bereits in den Startlöchern.&lt;/p&gt;


	&lt;p&gt;Nach dem 1.9.3 Release wird der Support für 1.9.1 eingestellt.&lt;/p&gt;




&lt;h4&gt;“Ruby, that Community and me” von &lt;a href="http://twitter.com/sora_h"&gt;sora_h&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;sorah_h, der seit kurzem Core Committer ist, stellte seinen Werdegang als jüngstes Mitglied des Core Teams vor. Er erklärte welche Dinge es Ihm ermöglicht haben sehr früh bereits mit Ruby in Kontakt zu kommen (u.a. Hackety Hack) und warb darum die jüngere Generation zu motivieren es Ihm gleich zu tun.&lt;/p&gt;




&lt;h4&gt;“The Real-Time Profiler for Ruby” von &lt;a href="http://sunagae.net"&gt;Takahiro Sunaga&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Es wurde der Real Time Profiler &lt;a href="http://sunagae.net/software/llprof"&gt;llprof&lt;/a&gt; vorgestellt, welcher es ermöglicht, ohne den hohen Overhead von ruby-prof Ruby Programme zu profilen. Dies findet weiterhin im Gegensatz zu ruby-prof in Echtzeit im Browser statt. Dort kann u.a. ein Graph oder eine Baumstruktur des aktuell laufenden Ruby Prozesses begutachtet werden.&lt;/p&gt;




&lt;h4&gt;“Dynamic Component System and Memory Reduction of VM for Embedded Systems” by Kiyoshi Ikehara&lt;/h4&gt;

	&lt;p&gt;Es wurde ein patch für Ruby 1.9.2 vorgestellt welcher es ermöglicht mehrere Prozesse getrennt innerhalb einer VM auszuführen. Als Beispiel wurde Sinatra verwendet.&lt;/p&gt;




&lt;h4&gt;“Lightweight Ruby” by Lightweight Ruby Development Team&lt;/h4&gt;

	&lt;p&gt;Der aktuelle Stand der Entwicklung des neuen Ruby Interpreters für Embedded Systeme wurde von matz vorgestellt. Eine erste Alpha Version soll ende Juli 2011 fertigstellt sein. Ein offizielles Release wird frühstens in der ersten Hälfte 2012 als Open Source veröffentlicht.&lt;/p&gt;




&lt;h4&gt;“Parallel world of CRuby’s GC” by &lt;a href="http://twitter.com/nari3"&gt;nari&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Der GC Maintainer nari stellt seine Ideen vor um die GC Mark and Sweep Implementierung parallel zu gestalten. Es wird dabei ein (wie er es nennt) “Task Steal” Ansatz verwendet. Dabei wird verhindert das der GC blockiert, in dem Aufgaben von GC Prozessen entwendet werden die selbst gerade blockiert sind.&lt;/p&gt;




&lt;h4&gt;“Ruby Interpreters in the Parallel Worlds” by &lt;a href="http://www.ci.i.u-tokyo.ac.jp/~sasada/index.en.html"&gt;Koichi Sasada&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Koichi stellt den aktuellen Stand der Entwicklung im Ruby trunk vor und erklärt Konzepte um die Ausführung auf Multiprozessor Maschinen zu beschleunigen. Es wird erneut die “Multiple Virtual Machine” erwähnt, wobei es sich um die Idee handelt, mehrere VM in einem Ruby auszuführen und so den “Global Lock” zu umgehen.&lt;/p&gt;




&lt;h4&gt;&lt;span class="caps"&gt;JIS&lt;/span&gt; Standardization von &lt;a href="http://blog.shugo.net/"&gt;Shugo Maeda&lt;/a&gt;&lt;/h4&gt;

	&lt;p&gt;Shugo sprach über den abgeschlossenen Standardisierungsprozess von Ruby. Er erklärte wie der Standard zu lesen sei, was er enthält und was ausgespart wurde.&lt;/p&gt;




&lt;h4&gt;Lightning Talks – Erste Runde&lt;/h4&gt;

	&lt;p&gt;Trunk Changes Statistic
- 9.2 commits a day&lt;/p&gt;


	&lt;p&gt;OS made by Ruby (Yoshihara Haruka)
- PerlOS&lt;/p&gt;


	&lt;p&gt;Creating Global Japanese Rubyist
- creating of TokyuRubyistMeetup&lt;/p&gt;


	&lt;p&gt;Rurima
- Japanese Ruby Referrnce Manual&lt;/p&gt;


	&lt;p&gt;James
- MacRuby speech talk dialog system
- codebrawl.com&lt;/p&gt;


	&lt;p&gt;Asp.Net vs Rails
- rails lost&lt;/p&gt;


	&lt;p&gt;Technology support rubykaigi.org&lt;/p&gt;


	&lt;p&gt;Rios:Proxy
 – Proxy Framework for &lt;span class="caps"&gt;CLI&lt;/span&gt;
 – emulate input/output&lt;/p&gt;


	&lt;p&gt;MacRuby Rainbow
 – rewritten &lt;span class="caps"&gt;IRB&lt;/span&gt;
 – integrated into Carbon
 – github.com/alloy&lt;/p&gt;


	&lt;p&gt;erb&lt;/p&gt;


	&lt;p&gt;Limiting Red&lt;/p&gt;




&lt;h4&gt;Lightning Talks – Zweite Runde&lt;/h4&gt;

	&lt;p&gt;Agile &lt;span class="caps"&gt;UCD&lt;/span&gt;
- Agile UX Live result
- Meetup &lt;span class="caps"&gt;CMS&lt;/span&gt;&lt;/p&gt;


	&lt;p&gt;Floating Point
- hard to use right
- decimal notation für Rational&lt;/p&gt;


	&lt;p&gt;BioRuby
- &lt;span class="caps"&gt;DNA&lt;/span&gt; Analyse&lt;/p&gt;


	&lt;p&gt;Chatting with Anime Voice Actors via Skype&lt;/p&gt;


	&lt;p&gt;Study Group versus Meetup Group&lt;/p&gt;


	&lt;p&gt;define_method&lt;/p&gt;


	&lt;p&gt;What Rubyists are missing is accounting&lt;/p&gt;


	&lt;p&gt;ActiveLdap
- Rails 3.1 Integration&lt;/p&gt;


	&lt;p&gt;MmapScanner&lt;/p&gt;


	&lt;p&gt;pebbles
- propose namespace for joke gems&lt;/p&gt;


	&lt;p&gt;C die hard&lt;/p&gt;




&lt;h4&gt;The Gate von Kakutani&lt;/h4&gt;

	&lt;p&gt;Die treibende Kraft hinter der RubyKaigi – Shintaro Kakutani – hielt eine Präsentation rund um die japanische Ruby Community und welchen Stellenwert die RubyKaigi darin einnahm. Er thematisierte die Zukunft ohne diese Konferenz und die eventuellen Möglichkeiten wie z.B. eine Kooperation mit der RubyConf.&lt;/p&gt;




&lt;h4&gt;Pendulum, PG, and the Hundred Year Old Language von matz&lt;/h4&gt;

	&lt;p&gt;Matz Keynote über die Gegenwart und Zukunft von Ruby.&lt;/p&gt;



          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-07-12:12152</id>
    <published>2011-07-12T20:24:00Z</published>
    <updated>2011-07-12T20:26:57Z</updated>
    <link href="http://www.ruby-mine.de/2011/7/12/matz-wechselt-den-arbeitgeber" rel="alternate" type="text/html" />
    <title>Matz wechselt den Arbeitgeber</title>
<content type="html">
            &lt;p&gt;An sich ist ihm das ja komplett frei gestellt, aber ich dachte, es könnte doch interessant sein: &lt;a href="http://blog.heroku.com/archives/2011/7/12/matz_joins_heroku/"&gt;Matz arbeitet neuerdings bei Heroku&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-07-08:12132</id>
    <published>2011-07-08T08:39:00Z</published>
    <updated>2011-07-08T08:40:13Z</updated>
    <link href="http://www.ruby-mine.de/2011/7/8/das-anz-hlen-hat-begonnen" rel="alternate" type="text/html" />
    <title>Das Anzählen hat begonnen</title>
<content type="html">
            &lt;p&gt;Irgendwann kommt die leidige Diskussion ja immer wieder auf. Ruby 1.9 oder 1.8? Wer Argumente gegen 1.8 für neue Projekte sucht, der wird ab heute ein neues bekommen: Die Gespräche über das End-Of-Life von Ruby 1.8 haben begonnen. Das altehrwürdige 1.8.6 wird eh kaum mehr gepflegt und 1.8.7 ist seit Jahren im Maintenance-Mode. Beide entwickeln sich nicht mehr fort, können allerdings auf eine breite Installationsbasis verweisen, was die Pflege durchaus noch sinnvoll macht. Gerade 1.8.7 wurde vor einigen Tagen mit einer neuen Version bedacht.&lt;/p&gt;

&lt;p&gt;Wer die Diskussion gleich live verfolgen will, kann das im &lt;a href="http://redmine.ruby-lang.org/issues/4996"&gt;Redmine Issue 4996&lt;/a&gt; tun. Momentan steht ein Ende der Maintenance im Juni 2012 im Raum, die Einstellung von sicherheitsrelevanten Fixes im Juni 2013. Aber das ist erstmal nur ein Vorschlag, es wäre nicht das erste Mal, dass sich in solch einer Situation ein Maintainer findet, der die Pflege &lt;a href="http://www.ruby-mine.de/2009/5/22/maintainerwechsel-bei-ruby-1-8-6"&gt;unbedingt fortführen will&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>bovi</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-07-04:12097</id>
    <published>2011-07-04T02:38:00Z</published>
    <updated>2011-09-12T08:44:01Z</updated>
    <category term="bovi [Autor]" />
    <category term="Hacks" />
    <link href="http://www.ruby-mine.de/2011/7/4/ruby-10-quine" rel="alternate" type="text/html" />
    <title>Ruby + 10 Quine</title>
<content type="html">
            &lt;p&gt;Ich habe gerade folgendes Quine von Yusuke Endoh &lt;a href="http://d.hatena.ne.jp/ku-ma-me/20090916/p1"&gt;gefunden&lt;/a&gt;:&lt;/p&gt;


&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;# ruby&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;l=&lt;span class="i"&gt;92&lt;/span&gt;.chr;eval s=&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;s=s.dump[r=1..-2].gsub(/(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;4&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;){4,}(?!&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)/){|t|'&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;+l*%d+&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;'%(t.size/2)};5.times{s=s.dump[r]};puts&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;# python&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="k"&gt;nprint(&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;# perl&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="k"&gt;nprint(&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;# lua&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;4&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;nprint(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;7&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;(* ocaml *)&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;8&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;nprint_endline&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;15&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;-- haskell&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;16&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;nimport Data.List;import Data.Bits;import Data.Char;main=putStrLn(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/* C */&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;n#include&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;nint main(void){char*s[501]={&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++intercalate&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;(c(tail(init(show(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/* Java */&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;npublic class QuineRelay{public static void main(String[]a){String[]s={&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++intercalate&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;(c(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;brainfuck&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;64&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;n++++++++[&amp;gt;++++&amp;lt;-]+++++++++&amp;gt;&amp;gt;++++++++++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++(concat(snd(mapAccumL h 2(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;110&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++g(length s)++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;22111211100111112021111102011112120012&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++concatMap(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;c-&amp;gt;let d=ord c in if d&amp;lt;11then&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;21002&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;111&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++g d++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;22102&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)s++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;21002111010120211222211211101000120211021120221102111000110120211202&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;))))))++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;64&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;};int i=0;for(;i&amp;lt;94;i++)System.out.print(s[i]);}}&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)))))++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;,0};int i=0;for(;s[i];i++)printf(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;%s&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;,s[i]);puts(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;);return 0;}&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;);c s=map(&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;s-&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++s++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;63&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)(unfoldr t s);t[]=Nothing;t s=Just(splitAt(if length s&amp;gt;w&amp;amp;&amp;amp;s!!w=='&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;'then 501else w)s);w=500;f 0=Nothing;f x=Just((if x`mod`2&amp;gt;0then '0'else '1'),x`div`2);g x= reverse (unfoldr f x);h p c=let d=ord c-48in(d,replicate(abs(p-d))(if d&amp;lt;p then '&amp;lt;'else '&amp;gt;')++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;);s=&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;# ruby&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;l=92.chr;eval s=&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;+(z=l*31)+&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;+s+z+&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;++&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;32&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;31&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;15&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;7&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;+l*&lt;span class="i"&gt;4&lt;/span&gt;+&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;n&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="ch"&gt;\\&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="ch"&gt;\&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;########### (c) Yusuke Endoh, 2009 ###########&lt;/span&gt;&lt;span class="ch"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Das besondere an diesem Quine?&lt;/p&gt;


&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ ruby QuineRelay.rb &amp;gt; QuineRelay.py&lt;tt&gt;
&lt;/tt&gt;$ python QuineRelay.py &amp;gt; QuineRelay.pl&lt;tt&gt;
&lt;/tt&gt;$ perl QuineRelay.pl &amp;gt; QuineRelay.lua&lt;tt&gt;
&lt;/tt&gt;$ lua QuineRelay.lua &amp;gt; QuineRelay.ml&lt;tt&gt;
&lt;/tt&gt;$ ocaml QuineRelay.ml &amp;gt; QuineRelay.hs&lt;tt&gt;
&lt;/tt&gt;$ runghc QuineRelay.hs &amp;gt; QuineRelay.c&lt;tt&gt;
&lt;/tt&gt;$ gcc -Wall -o QuineRelay QuineRelay.c &amp;amp;&amp;amp; ./QuineRelay &amp;gt; QuineRelay.java&lt;tt&gt;
&lt;/tt&gt;$ javac QuineRelay.java &amp;amp;&amp;amp; java QuineRelay &amp;gt; QuineRelay.bf&lt;tt&gt;
&lt;/tt&gt;$ beef QuineRelay.bf &amp;gt; QuineRelay.ws&lt;tt&gt;
&lt;/tt&gt;$ wspace QuineRelay.ws &amp;gt; QuineRelay.unl&lt;tt&gt;
&lt;/tt&gt;$ unlambda QuineRelay.unl &amp;gt; QuineRelay2.rb&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Und abschliessend:&lt;/p&gt;


&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;$ diff QuineRelay.rb QuineRelay2.rb&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


	&lt;p&gt;Ich bin verstört…&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>bovi</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-06-23:12060</id>
    <published>2011-06-23T14:44:00Z</published>
    <updated>2011-06-23T14:51:44Z</updated>
    <category term="bovi [Autor]" />
    <category term="Veranstaltungen" />
    <link href="http://www.ruby-mine.de/2011/6/23/germany-rb-2011-ruby-user-treffen-in-leipzig" rel="alternate" type="text/html" />
    <title>Germany.rb 2011 Ruby User Treffen in Leipzig</title>
<content type="html">
            &lt;p&gt;Wir haben wieder einen Termin gefunden! Am 20. und 21. August 2011 treffen wir uns zur zweiten Germany.rb in Leipzig im &lt;a href="http://sublab.org/"&gt;sublab&lt;/a&gt;. Wie immer gibt es keine Teilnahmegebühr und kein statisches Programm. Statt dessen gibt es Platz für Jeden um seine Ideen vorzutragen und sein Wissen zu teilen und zu erweitern.&lt;/p&gt;


	&lt;p&gt;Mehr Informationen gibt es auf &lt;a href="http://www.ruby-lang.org/de/news/2011/06/23/germany-rb-2011-in-leipzig/"&gt;der offiziellen Ruby Webseite&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.ruby-mine.de/2010/9/25/germany-rb-aftermath"&gt;Der Bericht mit allen Videos zur Germany.rb 2010&lt;/a&gt; ist auch verfügbar.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>quintus</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-06-21:12051</id>
    <published>2011-06-21T20:54:00Z</published>
    <updated>2011-06-21T20:55:25Z</updated>
    <category term="Allgemeines" />
    <category term="Quintus [Autor]" />
    <link href="http://www.ruby-mine.de/2011/6/21/ruby-talk-ml-und-comp-lang-ruby-getrennt" rel="alternate" type="text/html" />
    <title>Ruby-Talk-ML und comp.lang-ruby getrennt</title>
<content type="html">
            &lt;p&gt;James Edward Gray II. hat heute überrschend das Gateway zwischen der &lt;a href="http://www.ruby-forum.com"&gt;Ruby-Talk-Mailingliste&lt;/a&gt; und der Newsgroup &lt;a href="news:comp.lang.ruby"&gt;comp.lang.ruby&lt;/a&gt; heruntergefahren, da ihm die Wartung &lt;a href="http://www.ruby-forum.com/topic/1978201"&gt;ein zu großer Aufwand würde&lt;/a&gt; und er meint, dass die Ruby-Community zu groß für diese Verbindung geworden sei, sie habe sich ohnehin schon in einzelne Themenbereiche aufgespalten. Die ursprüngliche Funktion, die Ruby-Community zusammenzuhalten, als sie noch klein war, sei überholt und nicht mehr vonnöten. &lt;/p&gt;

&lt;p&gt;Heute um 22:25 Uhr &lt;a href="http://www.ruby-forum.com/topic/1978201#1006736"&gt;hat James verkündet&lt;/a&gt;, dass das Gateway geschlossen sei. Das bedeutet, dass die Usenet-Posts auf comp.lang.ruby nun nicht mehr auf der Mailingliste erscheinen werden, und umgekehrt auch Postings auf der Mailingliste die Newgroup nicht mehr erreichen. &lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-04-02:11834</id>
    <published>2011-04-02T14:44:00Z</published>
    <updated>2011-09-20T14:32:39Z</updated>
    <category term="Hacks" />
    <category term="skade [Autor]" />
    <category term="Syntax-Sonntag" />
    <link href="http://www.ruby-mine.de/2011/4/2/methoden-in-ketten-legen" rel="alternate" type="text/html" />
    <title>Methoden in Ketten legen</title>
<summary type="html">&lt;p&gt;Method chaining - also die implementierung einer Methode durch verketten 
mehrerer anderer ist durch Ruby on Rails zu einer gewissen Popularität gelangt. 
Während sich Rails hier auf ein einfaches Namenschema und alias 
verlässt, bietet DataMapper hier eine Technik an, die sich vorzüglich für einen 
Ausflug in Rubys Objektmodell eignet. Diese Gelegenheit will ich nicht an mir 
vorüber gehen lassen und die Implementierung namens Chainable hier vorstellen.&lt;p&gt;

&lt;a href="http://www.flickr.com/photos/25878086@N06/2731710806/" title="Chain by Sharky_MB { Away for 14 days}, on Flickr"&gt;&lt;/a&gt;</summary><content type="html">
            &lt;p&gt;Method chaining - also die implementierung einer Methode durch verketten 
mehrerer anderer ist durch Ruby on Rails zu einer gewissen Popularität gelangt. 
Während sich Rails hier auf ein einfaches Namenschema und alias 
verlässt, bietet DataMapper hier eine Technik an, die sich vorzüglich für einen 
Ausflug in Rubys Objektmodell eignet. Diese Gelegenheit will ich nicht an mir 
vorüber gehen lassen und die Implementierung namens Chainable hier vorstellen.&lt;p&gt;

&lt;a href="http://www.flickr.com/photos/25878086@N06/2731710806/" title="Chain by Sharky_MB { Away for 14 days}, on Flickr"&gt;&lt;/a&gt;
&lt;h3&gt;Ein kleiner Usecase&lt;/h3&gt;

&lt;p&gt;Wozu brauchen wir das Ganze eigentlich? Ruby ist eine Sprache, die besonders viel Wert auf die Komponentenweise konstruktion von Klassen legt. Anders als in Sprachen wie Java ist es durchaus erwünscht, Klassen in einzelnen Modulen zu implementieren und dann zusammen zu "mixen". Was aber, wenn bestimmte Methoden einer Klasse Verhalten gewinnen, wenn bestimmte Module inkludiert sind?&lt;/p&gt;

&lt;p&gt;Nehmen wir als kleines Beispiel eine Klasse, die gespeichert werden kann:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;#speicher-fu!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Hierzu schreiben wir uns ein Validierungsmodul. Validierung sollen immer ausgeführt werden, bevor die Person gespeichert wird:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Validations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    validate!&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;super&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  include &lt;span class="co"&gt;Validations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Das sieht zwar schön aus, funktioniert aber leider nicht. Schauen wir uns 
die Ableitungskette von Person an, fällt auch sofort auf, wieso:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;gt; &lt;span class="co"&gt;Person&lt;/span&gt;.ancestors&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [&lt;span class="co"&gt;Person&lt;/span&gt;, &lt;span class="co"&gt;Validations&lt;/span&gt;, &lt;span class="co"&gt;Object&lt;/span&gt;, &lt;span class="co"&gt;Kernel&lt;/span&gt;, &lt;span class="co"&gt;BasicObject&lt;/span&gt;] &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Wird ein Modul per include in eine Klasse eingebunden, landet es 
zwischen der Klasse und dem nächsten Objekt in der 
Ancestors-Kette. Ruft man also save auf, erwischt man stets die 
save-Methode von Person.&lt;/p&gt;

&lt;h3&gt;Wege heraus&lt;/h3&gt;

&lt;p&gt;Um kurz den Rails-Weg anzureissen, hier deren Variante, dieses Problem zu lösen:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;save_with_validations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    validate!&lt;tt&gt;
&lt;/tt&gt;    save_without_validations&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;alias&lt;/span&gt; &lt;span class="sy"&gt;:save_without_validations&lt;/span&gt; &lt;span class="sy"&gt;:save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;alias&lt;/span&gt; &lt;span class="sy"&gt;:save&lt;/span&gt; &lt;span class="sy"&gt;:save_with_validations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Wir benennen also die alte Methode um, implementieren eine neue, die den 
neuen Namen der alten Methode verwendet und geben der die neue dann den alten Namen. 
Diese Lösung hat ihren Charme und durchaus Vorteile (ich kann z.B. immernoch 
sehr bequem save_with_validations aufrufen), aber auch Nachteile: ich muss 
diesen Code zum Beispiel immer beim Einmixen eines Moduls ausführen, wenn das 
Feature an einem Modul hängt. Auch ist die Kette schwer nachzuverfolgen.&lt;/p&gt;

&lt;p&gt;Chainable geht einen anderen Weg. Die Implementierung ist kurz:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Chainable&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;chainable&lt;/span&gt;(&amp;amp;block)&lt;tt&gt;
&lt;/tt&gt;    mod = &lt;span class="co"&gt;Module&lt;/span&gt;.new(&amp;amp;block)&lt;tt&gt;
&lt;/tt&gt;    include mod&lt;tt&gt;
&lt;/tt&gt;    mod&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt; &lt;span class="c"&gt;# module Chainable&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Die Anwendung ist auch einfach:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  extend &lt;span class="co"&gt;Chainable&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  chainable &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;#speicher-fu!&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;module&lt;/span&gt; &lt;span class="cl"&gt;Validations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;save&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    validate!&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;super&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;Person&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  include &lt;span class="co"&gt;Validations&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Ich markiere also eine oder mehrere Methode als verkettbar, was mir im 
Folgenden erlaubt, diese Methode als Anfang einer Methodenkette zu verwenden. 
Ein Blick auf Hierarchie zeigt, wo die Magie liegt:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;gt; &lt;span class="co"&gt;Person&lt;/span&gt;.ancestors&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; [&lt;span class="co"&gt;Person&lt;/span&gt;, &lt;span class="co"&gt;Validations&lt;/span&gt;, &lt;span class="c"&gt;#&amp;lt;Module:0x000001009bb6e8&amp;gt;, Object, Kernel, BasicObject]&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Chainable erstellt also ein anonymes Modul und mixt dieses in 
die Klasse ein, auf die chainable aufgerufen wurde. Das führt dazu, dass die 
innerhalb des Block definierten Methoden innerhalb der Hierarchie eine Ebene 
nach oben rutschen. Damit ist sie sowohl für die Klasse als auch für alle 
danach eingemixtend Module als super verfügbar, worüber dann die 
Kette aufgebaut werden kann.&lt;/p&gt;

&lt;p&gt;Der Ansatz hat den Vorteil, dass alle Methoden einer Kette denselben Namen 
tragen und es ein klassisches Modell der Methodenverkettung verwendet: super.
Ersteres kann natürlich von Nachteil sein, wenn man Methoden ohne Features nach 
Namen aufrufen will (z.B. save_without_validations). Allerdings stellt sich 
hier die Frage, ob Verkettung für solche Fälle die richtige Lösung ist: Welche 
Methode rufe ich auf, wenn ich auf 2 Features verzichten will?&lt;/p&gt;

&lt;p&gt;Ein weiterer Vorteil ist die bessere Inspizierbarkeit: folgende kleine Methode
gibt mir die volle Methodenkette für einen Namen aus, zusammen mit dem Ort, wo die
Methoden definiert wurden (Achtung, source_location gibt es nur unter 1.9):&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;filter_chain&lt;/span&gt;(klass, meth)&lt;tt&gt;
&lt;/tt&gt;  chain = klass.ancestors.map &lt;span class="r"&gt;do&lt;/span&gt; |a| &lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      m = a.instance_method(meth)&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;next&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; m.owner != a&lt;tt&gt;
&lt;/tt&gt;      [m, m.source_location]&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;rescue&lt;/span&gt; &lt;span class="co"&gt;NameError&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;next&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  chain.compact&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;filter_chain(&lt;span class="co"&gt;Person&lt;/span&gt;, &lt;span class="sy"&gt;:save&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Viel Spaß beim in Ketten legen, der volle Text über DataMapper kommt dann auch bald.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>quintus</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-03-31:11826</id>
    <published>2011-03-31T22:00:00Z</published>
    <updated>2011-04-02T07:37:13Z</updated>
    <category term="Allgemeines" />
    <category term="Core" />
    <category term="Quintus [Autor]" />
    <link href="http://www.ruby-mine.de/2011/3/31/ruby-demn-chst-nur-noch-closed-source" rel="alternate" type="text/html" />
    <title>Ruby demnächst nur noch Closed-Source</title>
<content type="html">
            Wie unterrichtete Kreise erfahren haben wollen, übernimmt die &lt;a href="http://oracle.com"&gt;Oracle Corporation&lt;/a&gt; die maßgeblich an der Ruby-Entwicklung beteilgte Firma &lt;a href="http://engineyard.com"&gt;EngineYard&lt;/a&gt; für umgerechnet 240 Millionen Euro. Dem Sprecher von Oracle zufolge solle Ruby nun "um die Qualität, Produktivität und Attraktivität der Sprache zu fördern" nur noch als Closed-Source entwickelt werden. Die Binaries, die auf der noch nicht öffentlich zugänglichen Website &lt;a href="http://ruby.oracle.com"&gt;ruby.oracle.com&lt;/a&gt; zu haben sein werden, sollen jedoch nach wie vor kostenlos sein. Man werde auch weiterhin Binaries für Linux- und Mac-Systeme anbieten, verspricht die amerikanische Firma. Oracle werde aber eine kostenpflichtige "Cloud Edition" von Ruby veröffentlichen, die offenbar anstelle der bisherigen Makro-Funktion von Oracles "Cloud Office" benutzt werden kann.
&lt;br /&gt;&lt;br /&gt;
Der Hauptentwickler und Erfinder von Ruby, der Japaner Yukihiro "Matz" Matsumoto, äußerte sich bestürzt. Er werde sich fortan vollständig aus der Ruby-Entwicklung zurückziehen, und mit ihm der größte Teil des bisherigen Core-Teams. Er empfehle für die Zukunft einen Boykott der Sprache, postete er auf einer japanischen Ruby-Mailingliste: &lt;blockquote&gt;私たちに向かって、Oracleの敵対的な態度は、私たちは、Rubyプログラミング言語で開発を停止させる。これは、私が言うのは難しいが、もうRubyを使用しないでください。そのような組織をサポートしていません。&lt;/blockquote&gt;
Zugleich kündigte Oracle an, mit der demnächst erscheinenden Version 7 der Programmiersprache Java deren Lizenz so abzuändern, dass jegliche Software, die auf der Java Virtual Machine aufsetzt, nur noch als Closed-Source vertrieben werden darf. Dies veranlasste den führenden Kopf der JRuby-Implementation, Charles Oliver Nutter, zu einem hier nicht weiter zitierten, aber überaus unhöflichen Statement gegenüber Oracle.
Alle Hoffnungen ruhen nun auf der letzten freien Ruby-Implementation &lt;a href="http://rubini.us"&gt;Rubinius&lt;/a&gt;, deren Entwicklungsteam sich zwar gleichfalls geschockt zeigte, aber verlauten lies, man werde nun mit Hochdruck an der Fertigstellung von Rubinius 1.5 arbeiten, das vollständige Kompatibilität zum bisherigen MRI 1.9.2 besitzen solle.

&lt;h3&gt;Update&lt;/h3&gt;
Kommando zurück, das war nur ein Aprilscherz. Das Matz-Zitat ist auch nur ein passender vom Google-Übersetzer von Englisch nach Japanisch übersetzter Text. :-)
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-02-17:11720</id>
    <published>2011-02-17T11:04:00Z</published>
    <updated>2011-02-17T11:24:30Z</updated>
    <link href="http://www.ruby-mine.de/2011/2/17/mono-2-10-ver-ffentlicht" rel="alternate" type="text/html" />
    <title>Mono 2.10 veröffentlicht</title>
<content type="html">
            &lt;p&gt;Novell hat &lt;a href="http://www.mono-project.com/Release_Notes_Mono_2.10#Languages"&gt;die Version 2.10&lt;/a&gt; der alternativen .NET-Implementierung Mono veröffentlicht. Inwiefern ist das für Rubyisten relevant? Ab diesem Release enthalten die Installer für Linux und OS X einen Release von IronRuby und IronPython. Wer also bequem mal IronRuby ausprobieren möchte, kann nun den Installer installieren und einfach ir aufrufen:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;pre&gt;&lt;code&gt;[ skade Florian-Gilchers-MacBook-Pro ~ ] ir
IronRuby 1.1.2.0 on 2.10 (tarball Mon Feb 14 16:04:48 MST 2011)
Copyright (c) Microsoft Corporation. All rights reserved.

&amp;gt;&amp;gt;&amp;gt; RUBY_VERSION
=&amp;gt; &amp;quot;1.9.2&amp;quot;
&amp;gt;&amp;gt;&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Für FOSS-Anhänger wie mich: IronRuby ist übrigens seit geraumer Zeit zusammen mit der DLR (Dynamic Language Runtime) unter Apache 2.0 veröffentlicht.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-02-11:11648</id>
    <published>2011-02-11T17:25:00Z</published>
    <updated>2011-02-12T14:21:01Z</updated>
    <category term="Bibliotheken" />
    <category term="Dokumentation" />
    <category term="skade [Autor]" />
    <link href="http://www.ruby-mine.de/2011/2/11/die-drei-grossen-2-sequel" rel="alternate" type="text/html" />
    <title>Die drei Großen (2): Sequel</title>
<summary type="html">&lt;p&gt;Sequel ist wohl die DB-Zugriffsschicht, mit der sich die
wenigsten Rubyisten auskennen. Dabei ist sie meiner Meinung nach die
beste reine Skripting-Bibliothek von allen dreien. Das äussert sich
schon darin, dass Sequel mit keinerlei Core-Extensions wie
ActiveSupport oder Extlib daher kommt. Einige werden zwar optional
mitgeliefert, aber nicht standardmässig geladen.&lt;/p&gt;

&lt;p&gt;Wie bereits erwähnt, beschäftigt sich Sequel nur mit SQL und das
mit nur minimalen Abstraktionen - Sequel ist also kein ORM. Dafür
kommt Sequel mit der größten Anzahl an Datenbank-Adaptern, momentan
über 20. Implementierungen für verschiedene
Connection-Pooling-Strategien und Sharding finden sich auch.&lt;/p&gt;

&lt;p&gt;Plugins gibt es für viele interessante SQL-Funktionen, zum
Beispiel für Windows (also, nicht das OS) oder Recursive Table
Expressions.&lt;/p&gt;

&lt;p&gt;Darüber hinaus kommt Sequel mit einem Kommandozeilentool, dass
sich als Ersatz für den datenbankspezifischen Client verwenden
lässt, allerdings im Grunde nur IRB mit vorgeladener Datenbank
ist.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Sequel ist wohl die DB-Zugriffsschicht, mit der sich die
wenigsten Rubyisten auskennen. Dabei ist sie meiner Meinung nach die
beste reine Skripting-Bibliothek von allen dreien. Das äussert sich
schon darin, dass Sequel mit keinerlei Core-Extensions wie
ActiveSupport oder Extlib daher kommt. Einige werden zwar optional
mitgeliefert, aber nicht standardmässig geladen.&lt;/p&gt;

&lt;p&gt;Wie bereits erwähnt, beschäftigt sich Sequel nur mit SQL und das
mit nur minimalen Abstraktionen - Sequel ist also kein ORM. Dafür
kommt Sequel mit der größten Anzahl an Datenbank-Adaptern, momentan
über 20. Implementierungen für verschiedene
Connection-Pooling-Strategien und Sharding finden sich auch.&lt;/p&gt;

&lt;p&gt;Plugins gibt es für viele interessante SQL-Funktionen, zum
Beispiel für Windows (also, nicht das OS) oder Recursive Table
Expressions.&lt;/p&gt;

&lt;p&gt;Darüber hinaus kommt Sequel mit einem Kommandozeilentool, dass
sich als Ersatz für den datenbankspezifischen Client verwenden
lässt, allerdings im Grunde nur IRB mit vorgeladener Datenbank
ist.&lt;/p&gt;
&lt;h2&gt;Setup&lt;/h2&gt;

&lt;p&gt;Sequel kommt komplett mit allen Plugins in einem Gem, eventuell
benötigte Datenbankkonnektoren sind dabei ausgenommen. Wer also zum
Beispiel sqlite3 verwenden will, benötigt also noch den sqlite3-gem
oder alternativ data_objects und do_sqlite3.&lt;/p&gt;

&lt;p&gt;Am Anfang steht wie immer `require`, bei Sequel gibt es da
eigentlich nur 2 Varianten: core oder mit Modelschicht. Hierbei ist
zu beachten, dass sequel standardmässig die Modelschicht mitlädt,
core ist der Sonderwunsch.&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;sequel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;sequel-core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Die Datenbankverbindung stellt man über Connection-Strings
her:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;db = &lt;span class="co"&gt;Sequel&lt;/span&gt;.connect &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;postgres://postgres@localhost/my_example?encoding=utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;,&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="sy"&gt;:max_connections&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;10&lt;/span&gt;, &lt;span class="sy"&gt;:logger&lt;/span&gt; =&amp;gt; &lt;span class="co"&gt;Logger&lt;/span&gt;.new(&lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;log/db.log&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Wer schnell nur ein wenig rumspielen will, kann eine der
convenience-Methoden verwenden, am praktischsten ist #sqlite, das
sofort eine SQLite-DB im Speicher erstellt.&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;db = &lt;span class="co"&gt;Sequel&lt;/span&gt;.sqlite&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Extrem praktisch, wenn man nur mal schnell rumspielen will.&lt;/p&gt;

&lt;h2&gt;Queries&lt;/h2&gt;

&lt;p&gt;Sequel lebt vor allem von einem Objekt: Dataset. Datasets
repräsentieren die Beschreibung eines Datensatzes (also, einen
SQL-Query ;)) und können beliebig weiter verwendet und manipuliert
werden. Dazu besitzen sie verschiedene Methoden, die dann einen
Query auslösen. Datasets werden in der Anwendung immer durch das
Datenbank-Objekt erstellt:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt; people = db[&lt;span class="sy"&gt;:persons&lt;/span&gt;] &lt;span class="c"&gt;#alternativ db.from(:persons)&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Gibt uns einen Query für alle Zeilen der Tabelle “persons”.
Ausgeführt wird der Query, wenn wir irgendeine Methode aufrufen,
die auf Elemente des Datasets zugreift:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;people.all &lt;span class="c"&gt;#=&amp;gt; hoffentlich steckt dahinter nicht die Weltbevölkerung&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;people.first &lt;span class="c"&gt;#=&amp;gt; der erste&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;people[&lt;span class="sy"&gt;:age&lt;/span&gt; =&amp;gt; &lt;span class="i"&gt;13&lt;/span&gt;] &lt;span class="c"&gt;#=&amp;gt; alle, die endlich auf rubyforen.de dürfen&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Manipulationen eines Dataset-Objekts sind nicht-destruktiv und
geben immer ein neues Dataset zurück:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;children = people.filter { age &amp;lt; &lt;span class="i"&gt;13&lt;/span&gt; }&lt;tt&gt;
&lt;/tt&gt;silver_surfers = people.filter { age &amp;gt; &lt;span class="i"&gt;65&lt;/span&gt; }&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Gegenüber handgeschriebenen WHERE-Conditions hat die
Filter-Methode auch den Vorteil, dass sie beliebig häufig
aufgerufen werden kann:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;male_silver_surfers = silver_surfers.filter(&lt;span class="sy"&gt;:sex&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:male&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Ähnlich lassen sich SELECTs und andere Klauseln hinzufügen:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;male_silver_surfers.select(&lt;span class="sy"&gt;:age&lt;/span&gt;, &lt;span class="sy"&gt;:sex&lt;/span&gt;)&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Als letztes Stück Code Einführung möchte ich noch 2 Beispiele
aus der Doku zeigen, JOINs und Graphing:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;DB&lt;/span&gt;[&lt;span class="sy"&gt;:items&lt;/span&gt;].join(&lt;span class="sy"&gt;:order_items&lt;/span&gt;, &lt;span class="sy"&gt;:item_id&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:id&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; {&lt;span class="sy"&gt;:id&lt;/span&gt;=&amp;gt;order_items.id, &lt;span class="sy"&gt;:item_id&lt;/span&gt;=&amp;gt;order_items.item_id}&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="co"&gt;DB&lt;/span&gt;[&lt;span class="sy"&gt;:items&lt;/span&gt;].graph(&lt;span class="sy"&gt;:order_items&lt;/span&gt;, &lt;span class="sy"&gt;:item_id&lt;/span&gt; =&amp;gt; &lt;span class="sy"&gt;:id&lt;/span&gt;).first&lt;tt&gt;
&lt;/tt&gt;=&amp;gt; {&lt;span class="sy"&gt;:items&lt;/span&gt;=&amp;gt;{&lt;span class="sy"&gt;:id&lt;/span&gt;=&amp;gt;items.id}, &lt;span class="sy"&gt;:order_items&lt;/span&gt;=&amp;gt;{&lt;span class="sy"&gt;:id&lt;/span&gt;=&amp;gt;order_items.id, &lt;span class="sy"&gt;:item_id&lt;/span&gt;=&amp;gt;order_items.item_id}}&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Sequel kann also die flachen Rückgaben von JOINs wieder zu
geschachtelten Strukturen verwandeln. Eine äusserst praktische
Funktion, die es einem erspart, diese Verbindungen selbst wieder
aus dem Result zu ziehen.&lt;/p&gt;

&lt;p&gt;Ab hier übergebe ich an die Doku, die Queries sehr genau
beschreibt. Es gibt da noch viel zu finden.&lt;/p&gt;

&lt;p&gt;Das interessante an Sequel-Datasets ist weniger, dass sie eine
schöne DSL zum schreiben von SQL-Queries sind, sondern eher ihre
Eigenschaft, beliebig weitergefiltert und verfeinert werden zu
können. Statt also in meiner Applikation halbfertige SQL-Strings
rumzureichen bietet Sequel einen manipulierbaren Datentyp und
verwaltet alle Klauseln für den Nutzer und bleibt dabei so
datenbankunabhängig wie möglich.&lt;/p&gt;

&lt;p&gt;Die beschreibende Rolle von Datasets nutzt Sequel für einen
eleganten ORM-Mechanismus, der einem die Arbeit mit rohen Datensets
weiter vereinfacht: Sequel::Model.&lt;/p&gt;

&lt;h2&gt;Models&lt;/h2&gt;

&lt;p&gt;Sequel Models sind eigentlich ein Dekorator über einem Datenset.
Zuerst mal sehen sie nicht anders aus als die, die man aus
ActiveRecord kennt:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;People&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;Sequel&lt;/span&gt;::&lt;span class="co"&gt;Model&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;




&lt;p&gt;Wer eine andere Tabelle mit etwas Zucker haben will, kriegt
sogar ein kleines Stückchen Ruby-Magie präsentiert:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;People&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;Sequel&lt;/span&gt;::Model(&lt;span class="sy"&gt;:my_table&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Fängt man aber mit den Abfragen an, wird schnell klar, dass
diese Models eigentlich nur aufgehübschte Datasets sind:&lt;/p&gt;
&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="co"&gt;People&lt;/span&gt;.filter(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Daniel&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).first&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Wenig verwunderlich lassen sich also z.B. sehr einfach Models
über gefilterten Datasets implementieren:&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&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="code"&gt;&lt;pre&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;SilverSurfers&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;Sequel&lt;/span&gt;::&lt;span class="co"&gt;Model&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  set_dataset &lt;span class="co"&gt;DB&lt;/span&gt;[&lt;span class="sy"&gt;:people&lt;/span&gt;].filter (&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;age &amp;gt; ?&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="i"&gt;65&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;besitzt_internet_ab_60?&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="c"&gt;# logik&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;Assoziationen und Validierungen werden auch unterstützt, sollen
hier aber nicht vorgestellt werden. Wer eine Lib dafür kennt, kennt
sie alle.&lt;/p&gt;

&lt;p&gt;Wer die Dataset-API kennt, kommt mit Models sofort zurecht.
Sequels einziger zusätzlicher Job ist hier das Mapping roher
Datenbankantworten auf Objekte.&lt;/p&gt;

&lt;h2&gt;Fazit&lt;/h2&gt;

&lt;p&gt;Sequel in einem Satz: Angenehmer als SQL, sehr featurereich und
sehr fokussiert. Wer alles aus seiner SQL-Datenbank herausholen
will oder Skripte schreibt, die komplexe Transformationen der
Datenbank durchführen müssen ist mit Sequel sehr gut bedient.
Darüber hinaus ist die Bibliothek vorzüglich dokumentiert, solange
man weiss, was hinter den SQL-Konzepten steckt. Wer den Unterschied
zwischen WHERE und HAVING nicht kennt, wird hier auch nicht
schlauer. Die Modelschicht ist zwar ein klein wenig spartanisch,
bringt aber alles, was man sich so wünscht. Wer sich nur für
Objektmodellierung und nicht für SQL interessiert, greift hier
besser zu anderen Lösungen. Wer im großen Stil die Features von
SQL-Datenbanken ausnutzt, wird hier schnell fündig und glücklich,
da Sequel hier wenige Umwege zum Ziel einbaut.&lt;/p&gt;

&lt;p&gt;Zuletzt: Jeremy Evans “Blog II” (Das Sequel zu Blog ;) ) ist
sehr lesenswert, vor allem für jeden, der sich für SQL
interessiert. Und solltet ihr Jeremy auf einer Konferenz treffen:
sprecht mit ihm, man trifft selten nettere und kompetentere
Programmierer.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-01-09:11608</id>
    <published>2011-01-09T08:00:00Z</published>
    <updated>2011-01-08T14:51:02Z</updated>
    <category term="Syntax-Sonntag" />
    <link href="http://www.ruby-mine.de/2011/1/9/syntax-sonntag-noch-mal-picky" rel="alternate" type="text/html" />
    <title>Syntax-Sonntag: Noch mal picky</title>
<content type="html">
            &lt;p&gt;Diesmal nur ein ganz kurzer. Über das Picky Lambda kann man gerne ewig lange diskutieren, aber mir ist gestern noch folgende, selten erwähnte Kleinigkeit aufgefallen: wenn man das picky lambda verwendet, können die Argumentklammern weggelassen werden.&lt;/p&gt;

&lt;div class="CodeMacro"&gt;
&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;  f = -&amp;gt; a,b { puts a,b }&lt;tt&gt;
&lt;/tt&gt;  f[&lt;span class="i"&gt;1&lt;/span&gt;,&lt;span class="i"&gt;2&lt;/span&gt;] &lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;


&lt;p&gt;(Eigentlich will ich ja nur wissen, ob CodeRay damit zurecht kommt.)&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>skade</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-01-08:11607</id>
    <published>2011-01-08T14:45:00Z</published>
    <updated>2011-01-10T07:20:56Z</updated>
    <category term="Bibliotheken" />
    <category term="skade [Autor]" />
    <link href="http://www.ruby-mine.de/2011/1/8/die-drei-grossen-1-ar-dm-sequel" rel="alternate" type="text/html" />
    <title>Die drei Großen (1): AR, DM, Sequel</title>
<summary type="html">&lt;p&gt;Auf einem der letzten germany.rb-Treffen kam zwischendurch eine Frage auf, die wohl doch viele beschäftigt: was unterscheidet eigentlich die drei großen Persistenzbibliotheken ActiveRecord, DataMapper und Sequel? Ein Thema, dass schon so manchen hat fragen lassen, aber selten ordentlich beantwortet wurde. Daher will ich in einer kleinen Serie von Posts alle drei im Detail vorstellen. Dieser Post wird als Auftakt dienen und eine grobe Unterscheidung versuchen.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Auf einem der letzten germany.rb-Treffen kam zwischendurch eine Frage auf, die wohl doch viele beschäftigt: was unterscheidet eigentlich die drei großen Persistenzbibliotheken ActiveRecord, DataMapper und Sequel? Ein Thema, dass schon so manchen hat fragen lassen, aber selten ordentlich beantwortet wurde. Daher will ich in einer kleinen Serie von Posts alle drei im Detail vorstellen. Dieser Post wird als Auftakt dienen und eine grobe Unterscheidung versuchen.&lt;/p&gt;
&lt;h2&gt;Die beiden Fowlers: DataMapper und ActiveRecord&lt;/h2&gt;


	&lt;p&gt;DataMapper und ActiveRecord beschäftigen sich beide mit Objektpersistenz. Sie versuchen also, Ruby-Objekte auf Objekte in einer Persistenzschicht (z.B. Zeilen in einer relationalen Datenbank) zu passen und dabei einen Teil der Komplexität der Datenhaltung zu verbergen. Das macht sie selbst wiederum zu sehr komplexen Gebilden.&lt;/p&gt;


	&lt;p&gt;Wer nach dem Namensgeber der beiden Bibliotheken sucht, wird sofort 2 von Martin Fowler eingeführte Persistenzmodelle finden, die sich vor allem in ihrer Abstraktionsrichtung unterscheiden. In ActiveRecord wird die Struktur der Daten zuerst einmal von der Datenbank beschrieben. ActiveRecord inspiziert dann zur Laufzeit die Datenbank, um herauszufinden, wie deren Struktur ist, um sie dann nachzubilden. Im Falle der ActiveRecord-Implementierung in Rails funktioniert das nur teilweise: da Rails auf Features von &lt;span class="caps"&gt;SQL&lt;/span&gt;-Datenbanken wie Fremdschlüssel und Constraints verzichtet, müssen Relationen zwischen ActiveRecord-Klassen immernoch von Hand angegeben werden, es ist also noch Handarbeit erforderlich.&lt;/p&gt;


	&lt;p&gt;DataMapper geht anders vor: hier werden gleich alle zu persistierenden Eigenschaften am Ruby-Objekt definiert, DataMapper kümmert sich darum diese in die Datenbank zu bringen. DataMapper inspiziert dabei die Storage nicht, kann aber bestimmte Änderungen am Store selbst vornehmen: wird an einem DataMapper-Model eine Eigenschaft hinzugefügt, kann DataMapper zum Beispiel automatisch eine Spalte in einer &lt;span class="caps"&gt;SQL&lt;/span&gt;-Datenbank hinzufügen. Selbstverständlich geschieht das nur bei nicht-destruktiven Operationen. Ein Nebeneffekt der Sache ist, dass sich dieses Konzept auch sehr leicht auf andere Datenbanken als &lt;span class="caps"&gt;SQL&lt;/span&gt;-Datenbanken übertragen lässt, weshalb DataMapper auch andere Stores ausser &lt;span class="caps"&gt;SQL&lt;/span&gt; unterstützt. DataMapper unterstützt auch von Haus die Verwendung mehrerer Datenbanken auf einmal, was zum Beispiel in Mandantensystemen sehr praktisch ist. DataMapper kann auch Relationen zwischen verschiedenen Datenstores herstellen: so kann man zum Beispiel problemlos Verbindungen zwischen Objekten ziehen, die in zwei verschiedenen Datenbanken liegen, z.B. Redis und einer &lt;span class="caps"&gt;SQL&lt;/span&gt;-Datenbank.&lt;/p&gt;


	&lt;h2&gt;&lt;span class="caps"&gt;SQL&lt;/span&gt; auf Steroiden: Sequel&lt;/h2&gt;


	&lt;p&gt;Jeremy Evans Sequel wird gerne mit DM und AR in einem anderen Satz genannt, hat mit ihnen aber eher wenig gemein. Sequel hat zwar als Plugin eine Objekt-Modellierungsschicht wie DataMapper und ActiveRecord, ist jedoch in dieser Hinsicht am wenigsten geeignet. Sequel legt mit seinem Namen die Marschrichtung vor: &lt;span class="caps"&gt;SQL&lt;/span&gt;, aber so richtig. Wenn man das erste Mal Sequel sieht, sieht das Ganze wie eine Alternativsyntax für &lt;span class="caps"&gt;SQL&lt;/span&gt;-Queries aus, was häufig die Frage aufwirft: “warum dann nicht gleich &lt;span class="caps"&gt;SQL&lt;/span&gt;?”. Einmal natürlich, weil &lt;span class="caps"&gt;SQL&lt;/span&gt;-Queries zusammenbauen immer ein bisschen abstrahiert gehört: einmal Quotes vergessen, schon sind die Kreditkartendaten kaputt oder für 1.50$ pro Stück irgendwo im Internet erhältlich. Zum zweiten, weil bestimmte Operationen (zum Beispiel Auswahl einer zufälligen Spalte) in verschiedenen Datenbanksystemen subtil unterschiedlich funktionieren, die man sich nicht immer merken will. Sequel bietet darüber hinaus eine ganze Reihe weiterer angenehmer Sachen: lazy queries zum Beispiel, die sich in mehreren Schritten weiter verfeinern lassen sowie viele Plugins, die das arbeiten mit reichlich diffizilen Sachen und abstrusen Datenbankfeatures erleichtern. Zwar ist Sequel ohne Plugins auf die Schnittmenge aller &lt;span class="caps"&gt;SQL&lt;/span&gt;-Datenbanken beschränkt, wer aber gerne z.B. rekursive Subqueries in Postgres verwenden will, der wird in der Plugin-Sammlung fündig. Der generierte &lt;span class="caps"&gt;SQL&lt;/span&gt;-Code ist richtig schick.&lt;/p&gt;


	&lt;h2&gt;Weiteres vorweg&lt;/h2&gt;


	&lt;p&gt;Die drei hier vorgestellten Bibliotheken sind einer der Gründe, warum ich gerne Ruby verwende: alle 3 haben einen genauen Fokus und keine ist die Kopie einer anderen. Alle drei haben ihre Stärken und Schwächen und sind einen Blick wert. ActiveRecord und DataMapper sind zum Beispiel eher schlecht im Umgang mit nicht nach ihren Vorstellungen konstruierten &lt;span class="caps"&gt;SQL&lt;/span&gt;-Datenbanken, während Sequel hier die besten Ergebnisse liefert. Umgekehrt bedeutet Sequel relativ viel Arbeit, wenn eine Applikation nur Standardfälle der anderen beiden abdeckt.&lt;/p&gt;


	&lt;p&gt;Allen dreien ist eins gemein: eine lange Entwicklungszeit und die damit erreichte Einsatzreife. Bleibt nur die Frage, was die drei jetzt genau ausmacht, die ich in weiteren Folgen beantworten werde.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.ruby-mine.de/">
    <author>
      <name>bovi</name>
    </author>
    <id>tag:www.ruby-mine.de,2011-01-06:11517</id>
    <published>2011-01-06T23:29:00Z</published>
    <updated>2011-01-08T14:39:20Z</updated>
    <category term="bovi [Autor]" />
    <category term="Veranstaltungen" />
    <link href="http://www.ruby-mine.de/2011/1/6/euruko2011-inititialize" rel="alternate" type="text/html" />
    <title>EuRuKo2011.initialize</title>
<content type="html">
            &lt;p&gt;Beim &lt;a href="http://www.rug-b.de/"&gt;rug-b Treffen&lt;/a&gt; in Berlin scheinen heute weitere Neuigkeiten über die &lt;a href="http://euruko2011.org/"&gt;nächste EuRuKo&lt;/a&gt; bekanntgegeben worden zu sein. U.a. ist die Veranstaltung auf den 28. und 29. Mai 2011 fixiert worden. Und der Veranstaltungsort wird das &lt;a href="http://www.kino.com/"&gt;Kino International&lt;/a&gt; sein, nur knapp 600m von meinem Zweitwohnsitz in Berlin entfernt. Sehr cool!&lt;/p&gt;

&lt;br /&gt;&lt;small&gt;Quelle: http://dnbutler.com/&lt;/small&gt;
          </content>  </entry>
</feed>

