<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="de-DE" xmlns="http://www.w3.org/2005/Atom">
  <title>Thomas Baustert | Meine Gedanken zu Papier gebracht - Home</title>
  <id>tag:www.thomasbaustert.de,2012:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  <link href="http://www.thomasbaustert.de/blog/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://www.thomasbaustert.de/blog/" rel="alternate" type="text/html"/>
  <updated>2011-04-04T21:35:31Z</updated>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2011-04-04:206</id>
    <published>2011-04-04T21:30:00Z</published>
    <updated>2011-04-04T21:35:31Z</updated>
    <category term="Plugins"/>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="gem"/>
    <category term="plugin"/>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://www.thomasbaustert.de/blog/2011/4/4/amount_field_rails3-released" rel="alternate" type="text/html"/>
    <title>amount_field_rails3 released</title>
<content type="html">
            &lt;p&gt;Für ein Nebenprojekt in Rails3 benötige ich wieder mein Rails Gem &lt;a href=&quot;https://github.com/thomasbaustert/amount_field&quot;&gt;amount_field&lt;/a&gt;. Daher bin ich endlich dazu gekommen, es für Rails3 zu aktualisieren, wenn auch intern eher im Rails2-Style.&lt;/p&gt;


	&lt;p&gt;Infos unter &lt;a href=&quot;https://github.com/thomasbaustert/amount_field&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2011-03-04:196</id>
    <published>2011-03-04T17:58:00Z</published>
    <updated>2011-03-04T18:01:07Z</updated>
    <category term="clean code"/>
    <category term="programming"/>
    <category term="software craftsmanship"/>
    <link href="http://www.thomasbaustert.de/blog/2011/3/4/www-cleancoders-com" rel="alternate" type="text/html"/>
    <title>www.cleancoders.com</title>
<content type="html">
            &lt;p&gt;Ich habe schon immer gedacht, &lt;a href=&quot;http://www.objectmentor.com/omTeam/martin_r.html&quot;&gt;Uncle Bob&lt;/a&gt; ist ein wenig anders (im positiven Sinne), wenn es das Vermitteln von Wissen und Erfahrung geht.&lt;/p&gt;


	&lt;p&gt;Hier jetzt der neueste Streich. Es ist nicht die Tatsache, dass es Videos sind. Es ist das Wie :).&lt;/p&gt;


	&lt;p&gt;Es lohnt sich!&lt;/p&gt;


	&lt;p&gt;&lt;a href=&quot;http://www.cleancoders.com&quot;&gt;www.cleancoders.com&lt;/a&gt;&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2011-02-11:190</id>
    <published>2011-02-11T18:38:00Z</published>
    <updated>2011-02-11T18:43:54Z</updated>
    <category term="framework"/>
    <category term="programming"/>
    <link href="http://www.thomasbaustert.de/blog/2011/2/11/meine-erwartungen-an-ein-framework" rel="alternate" type="text/html"/>
    <title>Meine Erwartungen an ein Framework</title>
<content type="html">
            &lt;p&gt;Wenn ich ein Framework einsetze, habe ich folgende Erwartungen:&lt;/p&gt;


	&lt;ol&gt;
	&lt;li&gt;Es wurde aus einer laufenden Anwendung extrahiert&lt;/li&gt;
		&lt;li&gt;Es verfügt über eine hohe interne Qualität&lt;/li&gt;
		&lt;li&gt;Es ermöglicht einfache Testbarkeit meines Produktionscodes&lt;/li&gt;
		&lt;li&gt;Es lässt sich schnell und einfach installieren.&lt;/li&gt;
		&lt;li&gt;Es verfügt über gute Dokumentation und Beispiele.&lt;/li&gt;
		&lt;li&gt;Es bietet eine einfache und intiutive Schnittstelle&lt;/li&gt;
	&lt;/ol&gt;


	&lt;h4&gt;Es wurde aus einer laufenden Anwendung extrahiert.&lt;/h4&gt;


	&lt;p&gt;Das Framework muss aus einer bestehenden laufenden Anwendung extrahiert worden sein. Nur dadurch hat es (zumindest für eine Applikation) seine Funktionsfähigkeit bewiesen. Im Handwerk werden nur Techniken, Konzepte usw. genutzt und weitergegeben, die sich in der Praxis bewährt haben. Erst die Erfahrung lehrt, was geht und was nicht. Gleiches gilt für ein Framework.&lt;/p&gt;


	&lt;p&gt;Gute Beispiele sind Ruby on Rails oder Spring (letzteres zumindest wegen diesem Punkt). Ein Anti-Beispiel ist &lt;span class=&quot;caps&quot;&gt;EJB&lt;/span&gt; bis 3.0. Die Entwicklung auf der grünen Wiese hat wohl mehr Kosten beim Einsatz verursacht als Nutzen gebracht.&lt;/p&gt;


	&lt;h4&gt;Es verfügt über eine Hohe interne Qualität.&lt;/h4&gt;


	&lt;p&gt;Das Framework muss über eine hohe interne Qualität verfügen, d.h. gut lesbaren modularen Code
und eine hohe Testabdeckung bieten. Nur so finde ich Vertrauen in das Framework und bin bereit mich darauf zu verlassen. Warum sollte ich einem Framework vertrauen, dass schluderig programmiert wurde und nicht ausreichend automatisiert getestet wird?&lt;/p&gt;


	&lt;h4&gt;Es ermöglicht einfache Testbarkeit meines Produktionscodes.&lt;/h4&gt;


	&lt;p&gt;Das Framework muss mir auf einfache Art und Weise ermöglichen, meinen darauf aufbauenden 
Produktionscode zu testen. Andernfalls habe ich den Eindruck, die Entwickler haben dem Thema wenig Beachtung geschenkt und das lässt mich skeptisch im Bezug auf den Rest des Frameworks werden.&lt;/p&gt;


	&lt;p&gt;Auch hier ist Ruby on Rails ein sehr gutes Beispiel, da ich Tests leicht erstellen und ohne laufenden Webserver ausführen kann. Ein Anti-Beispiel ist auch hier &lt;span class=&quot;caps&quot;&gt;EJB&lt;/span&gt; bis 3.0, weil die Beans nur innerhalb des Containers getestet werden konnten und das Schreiben umständlich war. Eigentlich unglaublich, das soetwas jemals produktiv eingesetzt wurde (und wird). Bei 3.0 gibt es nun endlich POJOs und damit einfachere Testbarkeit.&lt;/p&gt;


	&lt;h4&gt;Es lässt sich schnell und einfach installieren.&lt;/h4&gt;


	&lt;p&gt;Wir alle sind immer unter Zeitdruck (zumindest gefühlt) und die Installation sollte daher einfach und zügig gehen. Wenn ich erst viele Abhängigkeiten auflösen muss, vergeht mir vermutlich die Lust und der Frust beginnt. Also bitte diese Arbeit nicht auf den Nutzer abwälzen.&lt;/p&gt;


	&lt;h4&gt;Es verfügt über gute Dokumentation und Beispiele.&lt;/h4&gt;


	&lt;p&gt;Eine gute Dokumentation, vor allem viele gute und einfache Beispiele helfen enorm bei der
Einarbeitung. Wenn ich direkt ein Archiv herunterladen, auspacken und loslegen kann, bin ich eher angefixt. Auch Videos sind hier eine gute Unterstützung.&lt;/p&gt;


	&lt;p&gt;Vielleicht sollte ich noch anfügen, dass das Framework keine Eierlegendevollmichsau sein sollte,
sondern sich auf eine Sache konzentrieren sollte, die es besonders gut macht.&lt;/p&gt;


	&lt;p&gt;Und Vorsicht mit sogenannten Standards! Ein Framework ist nicht Standard, weil ein Firma es als solches benennt. Standard soll nur werden, was sich über lange Zeit bewertet. Also ruhig hinterfragen.&lt;/p&gt;


	&lt;p&gt;Und was sind deine Kriterien?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2011-01-26:188</id>
    <published>2011-01-26T14:54:00Z</published>
    <updated>2011-01-26T14:55:47Z</updated>
    <category term="Mac"/>
    <category term="Produktivit&#228;t"/>
    <category term="iterm"/>
    <category term="kommandozeile"/>
    <category term="mac"/>
    <category term="produktivit&#228;t"/>
    <category term="terminal"/>
    <link href="http://www.thomasbaustert.de/blog/2011/1/26/tastenkombination-n-chstes-wort-in-iterm-und-terminal" rel="alternate" type="text/html"/>
    <title>Mac-Tastenkombination: vorheriges und n&#228;chstes Wort in iTerm und Terminal</title>
<content type="html">
            &lt;p&gt;Hier eine Lösung, um für ein deutsches Tastaurlayout unter Mac eine Tastaturkombi (Tastaturbelegung) für vorheriges oder nächstes Wort im Terminal bzw. im iTerm festzulegen.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2011/1/26/Bildschirmfoto_2011-01-26_um_15.39.51.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;h4&gt;Terminal&lt;/h4&gt;


	&lt;p&gt;Am einfachsten ist es den Hacken bei &#8220;Wahltaste als Meta-Taste setzen&#8221; zu aktivieren. Leider erzeugt &lt;code&gt;ALT-@&lt;/code&gt; dann nicht mehr das @-Symbol :(&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2011/1/26/Bildschirmfoto_2011-01-26_um_12.22.14.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Daher habe ich mich für &#8220;Ctrl-Taste Linkspfeil&#8221; und &#8220;Ctrl-Taste Rechtspfeil&#8221; entschieden. Dazu die Einstellungen des Terminal-Programms aufrufen und im Reiter &#8220;Einstellungen&#8221; die gewünschte auswählen. Dann rechts im Reiter &#8220;Tastatur&#8221; den Eintrag &#8220;Ctrl-Taste Linkspfeil&#8221; auswählen und auf Bearbeiten klicken. Folgende Einstellung sind zu tätigen. Den Eintrag im Textfeld erhält man durch &#8220;Esc&#8221; und danach &#8220;b&#8221; :&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2011/1/26/Bildschirmfoto_2011-01-26_um_12.18.22.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Analog dann für &#8220;Ctrl-Taste Rechtspfeil&#8221; mit &#8220;Esc&#8221; und &#8220;f&#8221;.&lt;/p&gt;


	&lt;h4&gt;iTerm&lt;/h4&gt;


	&lt;p&gt;Wer statt Terminal das Programm &lt;a href=&quot;http://iterm.sourceforge.net/&quot;&gt;iTerm&lt;/a&gt; verwendet, geht wie folgt vor. Unter &#8220;Bookmarks&#8221; den Eintrag &#8220;Manage Profiles &#8230;&#8221; aufrufen und unter &#8220;Keyboard Profiles&#8221; &#8220;Global&#8221; auswählen.&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2011/1/26/Bildschirmfoto_2011-01-26_um_12.19.29.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Den Eintrag &#8220;ctrl-num-cursor-left&#8221; auswählen bzw. neu anlegen und folgende Einstellungen vornehmen:&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2011/1/26/Bildschirmfoto_2011-01-26_um_12.19.47.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Eventuell den Hacken bei &#8220;Higi interception  priority&#8221; setzen. Analog für &#8220;ctrl-num-cursor-right&#8221; :&lt;/p&gt;


	&lt;p&gt;&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2011/1/26/Bildschirmfoto_2011-01-26_um_12.20.46.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;


	&lt;p&gt;Abei eine Liste einige wichtiger Tastaturkombis:&lt;/p&gt;


&lt;pre&gt;
Ctrl-a -&amp;gt; go to the start of command line
Ctrl-e -&amp;gt; go to the end of command line
Ctrl-p -&amp;gt; previous command in history
Ctrl-n -&amp;gt; next command in history
Ctrl-f -&amp;gt; next character in command line
Ctrl-b -&amp;gt; previous character in command line
Ctrl-r -&amp;gt; reverse search in history file
Ctrl-d -&amp;gt; delete current character
Ctrl-h -&amp;gt; backspace
Ctrl-k -&amp;gt; delete from the prompt to the end of command line
Ctrl-u -&amp;gt; delete from the prompt to the beginning of command line
Ctrl-_ -&amp;gt; undo (yes, but limited)
Meta-&amp;lt; -&amp;gt; go to beginning of history file
Meta-&amp;gt; -&amp;gt; go to end of history file
Ctrl-&amp;lt; -&amp;gt; go to previous word in command line
Meta-b -&amp;gt; go to previous word in command line
Ctrl-&amp;gt; -&amp;gt; go to next word in command line
Meta-f -&amp;gt; go to next word in command line
Meta-d -&amp;gt; delete next word in command line 
          (from the actual position of the prompt)
&lt;/pre&gt;

	&lt;p&gt;Und nun schön üben :)&lt;/p&gt;


	&lt;p&gt;Gibt es Alternativen? Welche Tastaturkombi hast du hinzugefügt?&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2011-01-16:184</id>
    <published>2011-01-16T16:14:00Z</published>
    <updated>2011-01-16T16:15:08Z</updated>
    <category term="Clean Code"/>
    <category term="clean code"/>
    <category term="programming"/>
    <category term="software craftsmanship"/>
    <link href="http://www.thomasbaustert.de/blog/2011/1/16/schreibe-code-wie-ein-autor" rel="alternate" type="text/html"/>
    <title>Schreibe Code wie ein Autor</title>
<content type="html">
            &lt;p&gt;Um mich beim Schreiben von Quellcode daran zu erinnern möglichst sauberen Quellcode zu schreiben, habe ich als Gedankenstütze die schöne Aussage &lt;em&gt;&#8220;Schreibe Code wie ein Autor&#8221;&lt;/em&gt; entdeckt (Quelle: &lt;a href=&quot;http://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;#38;s=books-intl-de&amp;amp;#38;qid=1295104648&amp;amp;#38;sr=1-1&quot;&gt;Clean Code&lt;/a&gt;).&lt;/p&gt;


	&lt;p&gt;Ich selber habe ein paar &lt;a href=&quot;http://thomasbaustert.de/publikationen&quot;&gt;Artikel in Fachzeitschriften&lt;/a&gt; und sogar ein &lt;a href=&quot;http://thomasbaustert.de/rails-buch&quot;&gt;Buch&lt;/a&gt; geschrieben. Wenn ich schreibe, habe ich eine Botschaft, ich möchte etwas vermitteln (meist fachliches Wissen). Und ich möchte, dass der Leser mich versteht. Ich schreibe den Artikel oder das Buch nicht für mich, sondern für den Leser.&lt;/p&gt;


	&lt;p&gt;Ok, ich schreibe auch für mich, weil man durch das Schreiben über ein Thema (oder auch durch das Präsentieren) das Thema selber besser versteht. Schreiben ist auch ein Stück Selbstverwirklichung und natürlich auch Marketing.&lt;/p&gt;


	&lt;p&gt;Letztlich hat man beim Schreiben immer den Leser vor Augen. Und genau so sollte es auch beim Schreiben von Quellcode sein! Sicher immer wieder fragen, ob den Code auch ein anderer leicht versteht (oder ich selbst zu einem späteren Zeitpunkt). Nicht aufhören, wenn es funktioniert. Erst aufhören, wenn der Code auch leicht verständlich ist.&lt;/p&gt;


	&lt;h4&gt;Lasse den Code reviewen&lt;/h4&gt;


	&lt;p&gt;Bevor ich einen Artikel oder ein Buch als fertig abgebe, lasse ich das Geschriebene von Freunden und Kollegen reviewen. Ich möchte ein Feedback, ob der Text verständlich ist und keine fachlichen Fehler enthält (und keine Rechtschreibfehler ;) ). Das macht vermutlich jeder Autor.&lt;/p&gt;


	&lt;p&gt;Auch diese Möglichkeit gibt es in der Softwareentwicklung und verbreitet sich als Praktik immer mehr. Ich spreche von Code Reviews und auch Pair Programming. So wie das Feedback dem Autor hilft, seinen Text zu überdenken, helfen Code Reviews den Quellcode verständlicher zu machen. Pair Programming ist quasi das permanente &#8220;Verständlichermachen&#8221; des Codes.&lt;/p&gt;


	&lt;p&gt;Also, immer daran denken: &lt;em&gt;&#8220;Schreibe Code wie ein Autor!&#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;h4&gt;Ressourcen&lt;/h4&gt;


	&lt;ul&gt;
	&lt;li&gt;Buch: &lt;a href=&quot;http://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;#38;s=books-intl-de&amp;amp;#38;qid=1295104648&amp;amp;#38;sr=1-1&quot;&gt;Clean Code&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Blog: &lt;a href=&quot;http://www.thomasbaustert.de/blog/2011/1/14/cleancode&quot;&gt;Clean Code &#8211; Oder der gute Programmierer&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2011-01-14:183</id>
    <published>2011-01-14T18:10:00Z</published>
    <updated>2011-01-16T17:21:36Z</updated>
    <category term="Clean Code"/>
    <category term="clean code"/>
    <category term="programming"/>
    <category term="software craftsmanship"/>
    <link href="http://www.thomasbaustert.de/blog/2011/1/14/cleancode" rel="alternate" type="text/html"/>
    <title>Clean Code - Oder der gute Programmierer</title>
<content type="html">
            &lt;p&gt;Immer wieder kosten IT-Projekte mehr als geplant oder scheitern ganz. Die Gründe sind vielschichtig und häufig nicht technischer Natur. Dennoch muss man sich fragen, was wir als Programmierer zum Erfolg von Projekten beitragen oder auch nicht.&lt;/p&gt;


	&lt;p&gt;Irgendwo habe ich gelesen: &lt;em&gt;&#8220;Schlechte Programmierer schreiben Code, der vom Computer verstanden wird. Gute Programmierer schreiben Code, der von Menschen (anderen Programmierern) verstanden wird.&#8221;&lt;/em&gt; (kennt jemand die Quelle?).&lt;/p&gt;


	&lt;p&gt;Das Thema des guten Programmierers ist komplex, aber das Zitat bringt die Sache auf den Punkt. Wenn es um das Schreiben von Quellcode geht, gibt es zwischen Programmierern sehr große Unterschiede.&lt;/p&gt;


	&lt;h4&gt;80% aller Programmierer Schreiben unsauberen Quellcode&lt;/h4&gt;


	&lt;p&gt;Wenn es nur um das Funktionieren des Quellcode geht, bekommen das vermutlich 80% aller Programmierer hin. Wenn es um das Schreiben von sauberen Quellcode geht, sind 80% aller Programmierer eher schlecht als gut. Und das finde ich sehr bedenklich, da sauberer Quellcode essentiell für den Erfolg eines Projekt (eines Softwaresystems) ist.&lt;/p&gt;


	&lt;p&gt;Was wenn Juristen, Medizinern, Architekten, Handwerkern so schludrig wären. Wo wären wir dann? Wahrscheinlich dort, wo wir jetzt mit der IT sind. Noch weit am Anfang.&lt;/p&gt;


	&lt;p&gt;Mit schlecht ist hier nicht vorsätzlich schlechte Arbeit gemeint. Eher eine Unwissenheit, Faulheit oder das fehlende Verständnis für die notwendigen Disziplinen eines guten Programmierers.&lt;/p&gt;


	&lt;p&gt;Vielleicht sind 80% sehr hoch gegriffen. Vielleicht habe ich einen besonders hohen Anspruch, was guten Quellcode ausmacht. Wenn ich sehe, was möglich ist und das mit dem vergleiche, was ich in Projekten sehe, neige ich zu 80%. Das schliesst meinen eigenen Code (zum Teil) mit ein :)&lt;/p&gt;


	&lt;h4&gt;Unsauberer Quellcode hat seinen Preis&lt;/h4&gt;


	&lt;p&gt;Sicher gibt es unzählige Anwendungen, die funktionieren. Es kann also nicht so schlecht um unsere Zunft bestellt sein oder? Aber zu welchem Preis funktionieren diese Systeme? Und vor allem zu welchem Preis der Wartung und Weiterentwicklung?&lt;/p&gt;


	&lt;p&gt;Sicher hat Software ihren Preis, denn die Entwicklung ist nach wie vor aufwendig. Was für den Manager ein Knopf auf der Seite ist, bedeutet für den Programmierer häufig ein Wunder schaffen. Entweder zahlt man den Preis (bei guten Programmierern) oder man zahlt ihn doppelt (bei schlechten Programmierern). Insgesamt kosten die meisten Projekt aber deutlich mehr als notwendig.&lt;/p&gt;


	&lt;p&gt;Ein für mich ganz wesentlicher Aspekt ist die interne Qualität des Quellcode, die langfristig deutlich zur Kostenreduzierung beiträgt. Der Punkt ist für mich wichtig, weil ich als Programmierer genau hier etwas beitragen kann. Und zwar, indem ich Quellcode schreibe, der nicht nur funktioniert, sondern auch für andere Programmierer gut lesbar und gut verständlich ist.&lt;/p&gt;


	&lt;h4&gt;Was ist sauberer, gut lesbarer, verständlicher Code?&lt;/h4&gt;


	&lt;p&gt;Prinzipien, Praktiken und Beispiele guten Quellcodes finden sich in CleanCode [1]. 
Pflichtlektüre!&lt;/p&gt;


	&lt;p&gt;Siehe auch &lt;a href=&quot;http://thomasbaustert.de/blog/2011/1/16/schreibe-code-wie-ein-autor&quot;&gt;Schreibe Code wie ein Autor&lt;/a&gt;&lt;/p&gt;


	&lt;h4&gt;Warum ist verständlicher Quellcode wichtig?&lt;/h4&gt;


	&lt;p&gt;80% aller Kosten für Software sind Wartungskosten. Die initiale Erstellungen nimmt also den kleineren Teil ein. Beim Schreiben von Code muss langfristiger gedacht werden.&lt;/p&gt;


	&lt;p&gt;Das Funktionieren des Features ist trotz aller Umstände immer möglich und wird häufig als einziges Mass für das Entwicklungsende verwendet. Es ist offensichtlich. Entweder es funktioniert oder es funktioniert nicht. Das für Menschen lesbarer Quellcode für die langfristige Wartung eine ganz wesentliche Rolle spielt wird nicht gesehen.&lt;/p&gt;


	&lt;p&gt;Das Projekt schreitet voran und es dauert immer länger, um Features zu entwickeln. Das Team verbringt immer mehr Zeit für die Stabilisierung des Entwicklungsprozesses und die Fehlerbehebung. Die Anzahl neuer Features pro Zeiteinheit sinkt und sinkt.&lt;/p&gt;


	&lt;p&gt;Wichtig ist zu erkennen, dass Programmierer 80% ihrer Zeit Code &lt;strong&gt;lesen&lt;/strong&gt; und nicht &lt;strong&gt;schreiben&lt;/strong&gt; (siehe auch &lt;a href=&quot;http://www.codinghorror.com/blog/2006/09/when-understanding-means-rewriting.html&quot;&gt;When understanding means rewriting&lt;/a&gt;). Ebenso wird ein Grossteil der Zeit mit dem Ändern von bestehenden Quellcode verbracht. Den kleinsten Anteil bildet das Neuschreiben von Code!&lt;/p&gt;


	&lt;p&gt;Stunden und Tage gezeichnet von Anforderungsanalyse, Diskussionen, Entwicklung, Fehlerbehebung usw. sind komprimiert im Code gelandet. Bei der Wartung oder Fehlerbehebung muss der (lesende) Programmierer dieses Wissen aus dem kryptischen Code wiedergewinnen. Er muss die Absicht des Originalprogrammierers verstehen, die Geschichte hinter dem Code, die Anforderungen, das Wissen aus Stunden und Tagen. Warum hat er es so gemacht und nicht anders? Gab es keine Alternative oder hat er sie nicht gesehen?&lt;/p&gt;


	&lt;p&gt;Das ist häufig sehr mühsam und zeitaufwendig, erfordert Konzentration und möglichst keine Ablenkung. (Und ist auch dann nicht immer einfach, wenn der Leser der ursprüngliche Programmierer ist.)&lt;/p&gt;


	&lt;p&gt;Je unverständlicher der Code, um so größer die Chance, dass er nicht ausreichend verstanden wird und Änderungen neue Fehler bringen. Je unsauberer der Code, um so aufwendiger wird die Wartung oder werden Refactorings.&lt;/p&gt;


	&lt;p&gt;Daher ist es mehr als notwendig, dass der Quellcode sehr aussagekräftig und lesbar ist. Das bekommt man nicht geschenkt und kann man sich nicht kaufen. Das ist eine &lt;strong&gt;Disziplin&lt;/strong&gt;, ein Handwerk, eine Kunst. Diese unterscheidet u.a. den Anfänger vom Meister, den schlechten vom guten Programmier. Schlecht verständlicher Quellcode ist die Wurzel allen Übels. Und wie gesagt, ich vermute, in 80% aller Projekte ist er eher schlecht als gut.&lt;/p&gt;


	&lt;p&gt;Am Beginn eines Projekt fällt das noch wenig auf. Aber wer auf hohe interne Qualität verzichtet, muss früher oder später dafür zahlen. Und zwar gewaltig. Ich halte es da mit der Aussage von &lt;a href=&quot;http://www.objectmentor.com/omTeam/martin_r.html&quot;&gt;Uncle Bob&lt;/a&gt; aus &lt;a href=&quot;http://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;#38;qid=1295026404&amp;amp;#38;sr=8-1&quot;&gt;Clean Code&lt;/a&gt; : &lt;em&gt;&#8220;The only way to make the deadline – the only way to go fast – is to keep the code as clean as possible at all times.&#8221;&lt;/em&gt;&lt;/p&gt;


	&lt;h4&gt;Gründe für unsauberen Code&lt;/h4&gt;


	&lt;p&gt;Warum gibt es so vielen schlechten Quellcode? Warum haben wir diesen Kern unserer Arbeit so schwer im Griff?&lt;/p&gt;


	&lt;p&gt;Kurz gesagt, weil es keine vernünftige Ausbildung gibt.&lt;/p&gt;


	&lt;p&gt;Vermutlich weil das IT-Handwerk noch so jung ist und wir erst nach und nach lernen, was wirklich wichtig ist. Am offensichtlichsten ist da, dass jemand programmieren kann, wenn das von ihm geschriebene Programm &#8220;funktioniert&#8221;. Und genau da bleiben die meisten Programmier stehen.&lt;/p&gt;


	&lt;p&gt;Das Programmieren, die tägliche Arbeit in der Diskussion mit Kollegen und am Rechner ist harte Arbeit. Das Erlernen erfordert viel Disziplin und Zeit.&lt;/p&gt;


	&lt;p&gt;Das deutsche Handwerk ist weltweit für die Qualität bekannt. Die Ausbildung gehört sicher zur besten in der Welt. Wenn ich Tischler werden will, mache ich eine Ausbildung bei einem Tischlerbetrieb. Der Meister lehrt mich in Theorie und vor allem Praxis. Mit genügend Motivation und Ehrgeiz werde ich zum Gesellen und nach Jahren auch zum Meister.&lt;/p&gt;


	&lt;p&gt;Affinität zum Thema, Motivation und Eigeninitiative sind für das Erlernen des Handwerks wichtig. Der Meister hilft mir dabei, ist mein Ausbildern und Mentor. Er sorgt dafür, dass ich das Richtige lerne (effektiv) und es richtig lerne (effizient). Das gibt es in der IT-Welt so (noch) nicht oder selten. Oder wo ist der Meister in meiner Stadt, bei dem ich in die Ausbildung gehe?&lt;/p&gt;


	&lt;p&gt;Es geht mir nicht um die Einführung eines Meisterbriefes für IT-Fachkräfte. Das ist eine andere Baustelle. Es geht um das Fehlen einer fundierte Ausbildung für Programmierer.&lt;/p&gt;


	&lt;h4&gt;Jeder bringt sich Programmieren selber bei&lt;/h4&gt;


	&lt;p&gt;Weder im Studium, in Instituten oder in Firmen erfolgt eine fundierte und angemessene Ausbildung. Eine Ausbildung die weiter geht als &#8220;Programmieren ist Funktionieren&#8221; (s.u.).&lt;/p&gt;


	&lt;p&gt;Jeder, den ich kenne, hat sich das Programmieren selber beigebracht. Und damit haben wir den ersten Teilzeitjob bekommen und sind in die Berufswelt als hauptberuflicher Programmierer eingetaucht. Und zwar mehr oder weniger von Null an.&lt;/p&gt;


	&lt;p&gt;Wo gibt es so etwas in anderen Bereichen? Bei Architekten, Medizinern, Juristen, Handwerkern usw.?
Fange ich irgendwo als Mediziner an, weil ich schon mal meinen Hund verarztet habe? Oder als Jurist, weil ich das Grundgesetz gelesen habe?&lt;/p&gt;


	&lt;p&gt;Klar lernt man nie aus und muss sich selber immer weiterbilden. Auch ein Tischler mit gerade bestandenem Meisterbrief ist nicht am Ende, sondern eher am Anfang. Er muss weiterhin viel Erfahrung sammeln und sich in Theorie und Praxis permanent weiterbilden. Aber er hat zumindest eine solide Ausbildung (von einem Meister) erhalten, die die Grundlage für die weiteren Schritte bildet.&lt;/p&gt;


	&lt;p&gt;Wenn man bedenkt, das die Softwareentwicklung ein so wichtiger Markt und anspruchsvoller Job ist, wundert mich die nicht vorhandene fundierte Ausbildung.&lt;/p&gt;


	&lt;p&gt;Der Zugang zur professionellen Arbeit ist wohl bei keiner Zunft so einfach, wie bei der Programmierung. Meines Wissen gibt es kaum Quereinsteiger bei Architekten, Juristen, Medizinern, aber verhältnismässig viele in der IT. Damit sage ich nichts gehen Quereinsteiger. Ich meine nur, dass die Einstiegshürde in anderen Bereichen wesentlich höher ist. Wäre sie in der IT ebenso hoch, gäbe es hier wesentlich weniger Quereinsteiger.&lt;/p&gt;


	&lt;p&gt;Jeder hat heute einen Computern. Man benötigt ein gewisse Affinität zu diesem (zur IT), kauft sich ein paar Bücher und bringt sich selbst Programmierung bei. So hat es vermutlich jeder von uns gemacht, egal ob Studium, Ausbildung oder Quereinsteiger.&lt;/p&gt;


	&lt;h4&gt;Programmieren ist nicht nur funktionieren&lt;/h4&gt;


	&lt;p&gt;Aber was genau bringt man sich bei? Erst einmal nur Code so zu schreiben, dass der Computer (Compiler) den Code versteht und ausführt. &#8220;Hey, er zeigt mir &#8216;Hello World!&#8217;&#8221;&lt;/p&gt;


	&lt;p&gt;Wenn ich Sprachkonstrukte nur richtig schreibe, versteht das der Computer und das Programm läuft. Hie und da schon fummelig und manchmal nervenzehrend, aber mit der nötigen Affinität insgesamt nicht so schwer.&lt;/p&gt;


	&lt;p&gt;Es hinterlässt den Eindruck, man muss nur lernen, Code so zu schreiben, dass der Computer ihn versteht. Programmieren wird mit &#8220;funktionieren&#8221; verbunden. Wenn der Code funktioniert, kann ich programmieren, wenn nicht, dann nicht. Das ist logisch und offensichtlich.&lt;/p&gt;


	&lt;p&gt;Was weniger offensichtlich ist, ist den Quellcode verständlich zu schreiben. Denn dass ist eine Disziplin und kann nicht so leicht nachvollzogen werden, wie ein laufendes oder nicht laufendes Programm.&lt;/p&gt;


	&lt;p&gt;Aber genau dieser weitere Schritt, macht den Unterschied zum guten Programmierer. Oder wie es Uncle Bob in Clean Code beschreibt: &lt;em&gt;&#8220;To many think we are done once the programm work&#8221;&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;Und es ist ein sehr großer Schritt (eigentlich viele viele kleine) und benötigt Disziplin und Zeit. Und hier scheidet sich dann die Spreu vom Weizen. Wer wirklich gewillt ist, weiter zu kommen, Schritt für Schritt. Und wer die Mühen und den Aufwand scheut und stehen bleibt. Wer Durchschnitt bleibt oder zum Meister wird. (Analog vom Karate-Änfanger zum Meister mit mehreren schwarzen Gürteln. Man schreitet Schritt für Schritt voran und erreicht den höchsten Grad vielleicht nie.)&lt;/p&gt;


	&lt;h4&gt;Keine Zeit für Weiterbildung&lt;/h4&gt;


	&lt;p&gt;Ein weiterer Grund weshalb viele auf der erste Stufe stehen bleiben ist die fehlende Zeit für Weiterbildung. Weil die Basis nicht reicht und weil sich in der IT-Welt alles Wissen ständig weiterentwickelt, muss man sich ständig weiterbilden.&lt;/p&gt;


	&lt;p&gt;Aber kaum hat man die Basis erlernt, startet man im Job. Und hier hat man eines nicht und das ist Zeit. Jedes Projekt läuft immer unter Hochdruck und die 40 Stunden pro Woche reichen dafür gerade aus. Eine Weiterbildung erfolgt nur, wenn man selber in der Freizeit Bücher liest oder ausprobiert. Und mittlerweile wird die Weiterbildung in der Freizeit quasi von jedem Mitarbeiter erwartet.&lt;/p&gt;


	&lt;p&gt;(Chef: &#8220;Für Weiterbildung ist jetzt keine Zeit. Machen sie es in der Freizeit, machen allen anderen Kollegen auch!&#8221;) Kein Wunder, das viele nur das Nötigste lernen, um im Job dranzubleiben.&lt;/p&gt;


	&lt;p&gt;Man kann nur hoffen, dass die Firma und die Kollegen wissen, was richtig ist und es richtig machen und diese quasi als Meister, Auszubildender oder Mentor fungieren. Und man selbst sein Wissen an andere weitergibt. Darüber hinaus kommt es eben auf die eigene Einstellung an.&lt;/p&gt;


	&lt;h4&gt;Bin ich ein guter Programmierer?&lt;/h4&gt;


	&lt;p&gt;Ich habe schon viel schlechten Code geschrieben. Die Anwendung funktioniert, keine Frage. Aber verständlicher Quellcode ist anders. Wie gesagt, ich wusste es nicht besser, denn ich habe es nie wirklich gelernt. Und das gilt für alle meine Kollegen auch.&lt;/p&gt;


	&lt;p&gt;Erst nach und nach habe ich wesentliche Disziplinen erkannt und erlernt und bin so stetig besser geworden. Ein wesentlicher Schritt nach vorne war das Lesen vieler Bücher, der Austausch mit gleich gesinnten Kollegen und ganz konkret der Einsatz der testgetriebene Entwicklung.&lt;/p&gt;


	&lt;h4&gt;Clean Code Developer &#8211; Software Craftsmanship&lt;/h4&gt;


	&lt;p&gt;Ich könnte hier eine Reihe weitere Punkte aufführen, aber stattdessen verweise ich lieber auf &lt;a href=&quot;http://clean-code-developer.de&quot;&gt;Clean Code Developer&lt;/a&gt;. Es enthält quasi alles, was ich für essentiell halte, um ein guter Programmierer zu werden oder zu sein.&lt;/p&gt;


	&lt;p&gt;Ob ein solides Verständnis von OO, der Einsatz von &lt;span class=&quot;caps&quot;&gt;TDD&lt;/span&gt;, von statischer Codeanalyse, Continuous Integration, Code Reviews, Pair Programming oder die eigene Weiterbildung. Alles, alles trägt letztendlich zu sauberem Quellcode bei!&lt;/p&gt;


	&lt;p&gt;Was mir gefällt, ist dass die vielen wichtigen Prinzipien und Praktiken schrittweise durch das Wertesystem durchlaufen werden. Zu einem Zeitpunkt konzentriert man sich immer auf ein paar Punkte. Dann wechselt man die Farbe und befolgt eine Zeit andere Werte. Am Ende angekommen, beginnt man von vorne. Durch das kontinuierliche Durchlaufen verinnerlicht man alle wesentliche Punkte. Werde ich mal ausprobieren.&lt;/p&gt;


	&lt;p&gt;Ebenso bin ich angetan von der Bewegung des &lt;a href=&quot;http://manifesto.softwarecraftsmanship.org/&quot;&gt;Software Craftsmanship&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Beide haben das selbe Ziel und zum grossen Teil die selben Prinzipien und Praktiken.&lt;/p&gt;


	&lt;h4&gt;Fazit&lt;/h4&gt;


	&lt;p&gt;Fehlende Ausbildung und fehlende Zeit sind zwei wesentliche Faktoren für schlechten Quellcode. Dieser führt früher oder später zu aufwendigerer Wartung, mehr Fehlern, weniger Zeit für neue Features und zu stetig steigenden Kosten.&lt;/p&gt;


	&lt;p&gt;In beiden Punkten sind wir Programmierer arme Schweine. Es liegt an uns, ob wir die Mühen und Anstrengungen auf uns nehmen, uns kontinuierlich zu verbessern, um zum &lt;a href=&quot;http://clean-code-developer.de&quot;&gt;Clean Code Developer&lt;/a&gt; werden.&lt;/p&gt;


	&lt;p&gt;In diesem Sinne, ich bin dann mal weg, mich weiterbilden!&lt;/p&gt;


	&lt;h4&gt;Resourcen&lt;/h4&gt;


	&lt;ul&gt;
	&lt;li&gt;[1] &lt;a href=&quot;http://www.amazon.de/Clean-Code-Handbook-Software-Craftsmanship/dp/0132350882/ref=sr_1_1?ie=UTF8&amp;amp;#38;qid=1295025165&amp;amp;#38;sr=8-1&quot;&gt;CleanCode, Robert C. Martin, Prentice Hall, 2008&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;[2] &lt;a href=&quot;http://clean-code-developer.de&quot;&gt;Clean Code Developer&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;[3] &lt;a href=&quot;http://manifesto.softwarecraftsmanship.org/&quot;&gt;Software Craftsmanship&lt;/a&gt;&lt;/li&gt;
	&lt;/ul&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2010-08-31:152</id>
    <published>2010-08-31T20:06:00Z</published>
    <updated>2010-08-31T20:07:34Z</updated>
    <category term="Konferenz"/>
    <category term="Rails"/>
    <category term="konferenz"/>
    <category term="rails"/>
    <category term="rails-konferenz"/>
    <link href="http://www.thomasbaustert.de/blog/2010/8/31/aus-rk-orga-ausgestiegen" rel="alternate" type="text/html"/>
    <title>Aus RK-Orga ausgestiegen</title>
<content type="html">
            &lt;p&gt;
Ich bin vergangene Woche aus dem Orga-Team der &lt;a href=&quot;http://www.rails-konferenz.de/blog/72/rails-konferenz-2010&quot;&gt;Rails-Konferenz&lt;/a&gt; ausgestiegen. 
Die Organisation und Planung hat zuletzt nicht mehr meinen Vorstellungen entsprochen.
Es hat mir dadurch weniger Spaß gemacht und beruflich bin ich auch sehr eingespannt. 
&lt;/p&gt;

&lt;p&gt;
In den vergangenen 4 Jahren haben wir immer sehr gutes Feedback zur Konferenz erhalten. Daher möchte ich mich auf diesem Weg herzlich bei alle Sponsoren, Helfern und Teilnehmern für die prima Unterstützung in den Jahren bedanken. Ohne Euch wäre die Konferenz nicht so erfolgreich gewesen!
&lt;/p&gt;

&lt;p&gt;
Vielleicht finde ich 2011 die Motivation und Zeit eine Konferenz in Hamburg zu organisieren.
Mal sehen, in wie weit Interesse dafür besteht.
&lt;/p&gt;

&lt;p&gt;
Ich wünsche allen Beteiligten eine gute Zeit, vielleicht sieht man sich mal wieder.
&lt;/p&gt;


&lt;p&gt;
Bis dahin.
&lt;/p&gt;

&lt;p&gt;
Danke und Gruß,
Thomas
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2010-02-22:103</id>
    <published>2010-02-22T13:19:00Z</published>
    <updated>2010-02-22T13:20:16Z</updated>
    <category term="buch"/>
    <category term="publikationen"/>
    <category term="rails"/>
    <link href="http://www.thomasbaustert.de/blog/2010/2/22/keine-4-auflage-von-rwdmror" rel="alternate" type="text/html"/>
    <title>Keine 4. Auflage von RWDMROR</title>
<content type="html">
            &lt;p&gt;
  Aufgrund einiger Nachfragen, hier kurz eine &quot;Pressemitteilung&quot; :)
&lt;/p&gt;
&lt;p&gt;
  Zum Buch &quot;Rapid Web Development mit Ruby on Rails&quot; wird es erstmal keine 4. Auflage geben.
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://ralfwirdemann.de&quot;&gt;Ralf&lt;/a&gt; und ich sind vor allem aus Zeitgründen privater und beruflicher Art nicht in der Lage, eine neue Auflage zu Rails 3 zu schreiben. Kurzfristig gab es die Idee, dass uns 
&lt;a href=&quot;http://phillipoertel.com&quot;&gt;Phillip Oertel&lt;/a&gt; unterstützt, aber der hat dann ebenfalls aus Zeitgründen passen müssen.
&lt;/p&gt;
&lt;p&gt;
Die Entscheidung ist uns nicht leicht gefallen, aber vorerst geht es nicht anders.
&lt;/p&gt;
&lt;p&gt;
Vielen Dank an aller Leser für das Lob und die Anregungen!
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-11-19:70</id>
    <published>2009-11-19T20:09:00Z</published>
    <updated>2009-11-22T15:04:16Z</updated>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="irb"/>
    <category term="rails"/>
    <category term="rails-console"/>
    <link href="http://www.thomasbaustert.de/blog/2009/11/19/history-der-rails-console-reaktiviert" rel="alternate" type="text/html"/>
    <title>History der Rails-Console reaktiviert</title>
<content type="html">
            &lt;p&gt;
Irgendwann, vermutlich nach einem Update von Ruby und/oder Rails, stand die History meiner Rails Console nicht mehr zur Verfügung.
&lt;/p&gt;&lt;p&gt;
Nachdem ich damit eine gewisse Zeit leben konnte, wollte ich heute dem Grund auf die Schliche kommen. 
&lt;/p&gt;&lt;p&gt;
Nach einigem Probieren kam ich darauf, dass die Konsole und deren History unter &lt;code&gt;~/.irb_history&lt;/code&gt; schon funktioniert. Sie wird allerdings durch die Datei &lt;code&gt;~/.rdebug_hist&lt;/code&gt; erweitert. 
&lt;/p&gt;&lt;p&gt;
Ein Durchlaufen der einzelnen Einträge durch &quot;Pfeil-Taste hoch&quot; lief erst durch die Einträge des Debuggers und fand dann irgendwann auch die Einträge aus &lt;code&gt;~/.irb_history&lt;/code&gt;. Man musste nur oft genug Tippen :).
&lt;/p&gt;&lt;p&gt;
Ein Löschen der Datei &lt;code&gt;~/.rdebug_hist&lt;/code&gt; führte dazu, dass die letzten Einträge in der Konsole beim nächsten Aufruf sofort zur Verfügung standen.
&lt;/p&gt;&lt;p&gt;
Die Datei &lt;code&gt;~/.rdebug_hist&lt;/code&gt; wird durch ruby-debug (genauer &lt;code&gt;ruby-debug-0.10.3/cli/ruby-debug/interface.rb&lt;/code&gt;) eingelesen und geschrieben.  Ich habe den Code noch nicht ganz durchschaut, aber die Datei wurde trotz des Einsatzes des Debuggers bisher nicht wieder erzeugt. Sicherheitshalber habe ich die Datei selbst schreibgeschützt angelegt, um eine erneute Erzeugung zu vermeiden.
&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
touch ~/.rdebug_hist
chmod 400 ~/.rdebug_hist
&lt;/code&gt;&lt;/pre&gt;

&lt;h4&gt;Logging in der Rails-Console reaktiviert&lt;/h4&gt;

&lt;p&gt;
Darüber hinaus habe ich das Aktivieren und Deaktivieren der Logausgaben
in der Rails-Konsole wieder hinbekommen. Meine &lt;code&gt;~/.irbrc&lt;/code&gt; sieht wie folgt aus:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;

&lt;span class=&quot;linenum&quot;&gt;    1&lt;/span&gt; &lt;span class=&quot;source source_ruby&quot;&gt;&lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;rubygems&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;    2&lt;/span&gt; &lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;wirble&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;    3&lt;/span&gt; &lt;span class=&quot;meta meta_require meta_require_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;pp&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;    4&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;    5&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Wirble&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;init
&lt;span class=&quot;linenum&quot;&gt;    6&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Wirble&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;colorize
&lt;span class=&quot;linenum&quot;&gt;    7&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;    8&lt;/span&gt; &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;ri&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;*&lt;/span&gt;names&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;    9&lt;/span&gt;   system&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby string_quoted_double_ruby_mod&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;%{&lt;/span&gt;ri &lt;span class=&quot;source source_ruby source_ruby_embedded source_ruby_embedded_source&quot;&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;#{&lt;/span&gt;names&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;map &lt;span class=&quot;punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;variable variable_other variable_other_block variable_other_block_ruby&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_variable punctuation_separator_variable_ruby&quot;&gt;|&lt;/span&gt; name&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;to_s&lt;span class=&quot;punctuation punctuation_section punctuation_section_scope punctuation_section_scope_ruby&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;join&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt; &lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   10&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   11&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;   12&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;ENV&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;include?&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;RAILS_ENV&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;   13&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;   14&lt;/span&gt;   &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;sql&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   15&lt;/span&gt;     &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;connection&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;select_all&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;query&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   16&lt;/span&gt;   &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   17&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;   18&lt;/span&gt;   &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;logon&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   19&lt;/span&gt;     set_logger &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;STDOUT&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   20&lt;/span&gt;   &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   21&lt;/span&gt;   
&lt;span class=&quot;linenum&quot;&gt;   22&lt;/span&gt;   &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;logoff&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   23&lt;/span&gt;     set_logger &lt;span class=&quot;variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby&quot;&gt;@&lt;/span&gt;logger&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   24&lt;/span&gt;   &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   25&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;   26&lt;/span&gt;   &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;get_logger&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   27&lt;/span&gt;     &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;connection&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;instance_variable_get&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;@logger&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   28&lt;/span&gt;   &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   29&lt;/span&gt; 
&lt;span class=&quot;linenum&quot;&gt;   30&lt;/span&gt;   &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;set_logger&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   31&lt;/span&gt;     &lt;span class=&quot;variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby&quot;&gt;@&lt;/span&gt;logger&lt;/span&gt; &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_augmented keyword_operator_assignment_augmented_ruby&quot;&gt;||=&lt;/span&gt; get_logger
&lt;span class=&quot;linenum&quot;&gt;   32&lt;/span&gt;     &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_other punctuation_separator_other_ruby&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;connection&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;instance_variable_set&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;@logger&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_object punctuation_separator_object_ruby&quot;&gt;,&lt;/span&gt; logger&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   33&lt;/span&gt;   &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;linenum&quot;&gt;   34&lt;/span&gt;   
&lt;span class=&quot;linenum&quot;&gt;   35&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;linenum&quot;&gt;   36&lt;/span&gt; &lt;/pre&gt;

&lt;p&gt;
Update: Ich nutze Rails 2.3.4 und Ruby ruby 1.8.7
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-09-16:44</id>
    <published>2009-09-16T21:17:00Z</published>
    <updated>2009-09-16T21:18:19Z</updated>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="include"/>
    <category term="ruby"/>
    <link href="http://www.thomasbaustert.de/blog/2009/9/16/ruby-include-part-i" rel="alternate" type="text/html"/>
    <title>Ruby include Part I</title>
<content type="html">
            &lt;p&gt;
Ein häufiger Denkfehler beim Einbinden eines Moduls per &lt;span class=&quot;code&quot;&gt;include&lt;/span&gt; 
in eine Klasse ist, dass die Methoden aus dem Modul tatsächlich in die Klasse eingefügt werden.
Dem ist &lt;b&gt;nicht&lt;/b&gt; so. Hier ein Beispiel:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M1&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M1#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Der Aufruf von &lt;span class=&quot;code&quot;&gt;include M1&lt;/span&gt; führt intern &lt;span class=&quot;bold&quot;&gt;nicht&lt;/span&gt;
zu folgendem Code:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M1#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Tatsächlich wird durch &lt;span class=&quot;code&quot;&gt;include&lt;/span&gt; eine anonyme Proxyklasse erzeugt, 
die auf das Modul verweist und die Klasse &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; erhält eine Referenz auf diese Proxy-Klasse:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;Proxy&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;&amp;gt;&lt;/span&gt; proxy
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;
a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Im obigen Beispiel findet Ruby die Methode &lt;span class=&quot;code&quot;&gt;foo&lt;/span&gt; also nicht in der 
Klasse &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt;, sondern (über die Proxy-Klasse) im Modul 
&lt;span class=&quot;code&quot;&gt;M1&lt;/span&gt;.
&lt;/p&gt;

&lt;h4&gt;Suche entlang der Vererbungshierachie&lt;/h4&gt;

&lt;p&gt;
Grundsätzlich gilt: Um eine Methode auszuführen, muss Ruby die Definition
der Methode finden und sucht die Methode dazu entlang der Vererbungshierachie. 
Ein Beispiel:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;span class=&quot;entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby&quot;&gt; &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby&quot;&gt;&amp;lt;&lt;/span&gt; B&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M2&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;
a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo
&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Damit ergibt sich diese Suchreihenfolge:
&lt;/p&gt;

&lt;pre&gt;
1) A
2) M2 (über proxy)
3) M1 (über proxy)
4) B
&lt;/pre&gt;

&lt;p&gt;
Die Vererbungshierachie sieht wie folgt aus:
&lt;/p&gt;

&lt;pre&gt;
A -&gt; (proxy-&gt;M2) -&gt; (proxy-&gt;M1) -&gt; B
&lt;/pre&gt;

&lt;p&gt;
Es wird bei der Klasse &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; begonnen. Wird die Methode nicht gefunden, 
wird im Modul &lt;span class=&quot;code&quot;&gt;M2&lt;/span&gt; gesucht. Ist die Methode hier nicht vorhanden, wird 
im Modul &lt;span class=&quot;code&quot;&gt;M1&lt;/span&gt; gesucht und existiert die Methode hier nicht, wird in der 
Superklasse &lt;span class=&quot;code&quot;&gt;B&lt;/span&gt; nachgeschaut. Dort wiederholt sich die Suche.
&lt;/p&gt;
&lt;p&gt;
Daher hat eine in der Klasse &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; definierte Methode immer 
Vorrang vor einer gleichnamigen aus einem inkludierten Modul:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M1&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M1#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;&amp;gt;&lt;/span&gt; proxy &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;

  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;A#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;
a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;A#foo&quot;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Ruby sucht die Methode entlang der Vererbungshierachie und findet die Methode 
in der Klasse &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; bevor es im Modul &lt;span class=&quot;code&quot;&gt;M1&lt;/span&gt;
sucht. 
&lt;/p&gt;

&lt;h4&gt;Modulmethode über super aufrufen&lt;/h4&gt;

&lt;p&gt;
Es ist sicher bekannt, dass die Methode &lt;span class=&quot;code&quot;&gt;super&lt;/span&gt; dazu dient, 
eine gleichnamige Methode in der Superklasse aufzurufen. Beispiel:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;SuperClass&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;SuperClass#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;span class=&quot;entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby&quot;&gt; &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby&quot;&gt;&amp;lt;&lt;/span&gt; SuperClass&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;A#foo: &lt;span class=&quot;source source_ruby source_ruby_embedded source_ruby_embedded_source&quot;&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt; 
a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;A#foo: SuperClass#foo&quot;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Was vielleicht nicht sofort einleuchtet ist, dass auch die Modulmethode über 
&lt;span class=&quot;code&quot;&gt;super&lt;/span&gt; aufgerufen werden kann. Das Modul befindet sich 
(wie die Superklasse auch) in der Vererbungshierachie und daher kann sowohl die 
Superklassenmethode, als auch die Modulmethode über &lt;span class=&quot;code&quot;&gt;super&lt;/span&gt; 
aufgerufen werden:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M1&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M1#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;

 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;A#foo: &lt;span class=&quot;source source_ruby source_ruby_embedded source_ruby_embedded_source&quot;&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;keyword keyword_control keyword_control_pseudo-method keyword_control_pseudo-method_ruby&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;
a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;A#foo: M1#foo&quot;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;h4&gt;Vorrang beim Einbinden von Modulen&lt;/h4&gt;

&lt;p&gt;
Werden zwei Modul eingebunden und erhalten diese dieselbe Methode, so
wird die Methode des zuletzt inkludierten Moduls verwendet.
Im Beispiel &lt;span class=&quot;code&quot;&gt;M2&lt;/span&gt;:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M1&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M1#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M2&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M2#foo&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;
&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M2&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;
a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; M2#foo
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;h4&gt;Einschränkung der Sichtbarkeit&lt;/h4&gt;

&lt;p&gt;
Mit dem Wissen um die Wirkung von &lt;span class=&quot;code&quot;&gt;include&lt;/span&gt;, wird auch klar, 
warum die Einschränkung der Sichtbarkeit wie folgt &lt;span class=&quot;bold&quot;&gt;nicht&lt;/span&gt; 
möglich ist:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M1&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;mod_method1&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;mod_method1&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M2&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;mod_method2&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;mod_method2&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;

 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;private&lt;/span&gt;
   &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M2&lt;/span&gt; &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; method mod_method2 is still public
&lt;/span&gt;&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;mod_method1 &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;mod_method1&quot;
&lt;/span&gt;&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;mod_method2 &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;mod_method2&quot;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Die Methoden aus dem Modul &lt;span class=&quot;code&quot;&gt;M2&lt;/span&gt; sind öffentlich (public), 
obwohl das Modul nach dem Schlüsselwort &lt;span class=&quot;code&quot;&gt;private&lt;/span&gt; eingebunden wird. 
Und zwar, weil die Methode aus dem Modul nicht in die Klasse eingebunden werden, sondern 
die Klasse auf das Modul verweist (über den Proxy) und 
&lt;span class=&quot;code&quot;&gt;mod_method2&lt;/span&gt; in &lt;span class=&quot;code&quot;&gt;M2&lt;/span&gt; öffentlich ist.
&lt;/p&gt;

&lt;p&gt;
Korrekt geht es wie folgt:
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M2&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;private&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;mod_method2&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;mod_method2&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M1&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M2&lt;/span&gt;

 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   mod_method2
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo         &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;mod_method2&quot;
&lt;/span&gt;&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;mod_method1 &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;mod_method1&quot;
&lt;/span&gt;&lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;mod_method2 &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; NoMethodError: private method ‘mod_method2’ called
&lt;/span&gt;&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt;&amp;lt;A:0x108d8&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Wenn eine Modulmethode nur für interne Implementierung dient, sollte die
Methode auf jeden Fall als &lt;span class=&quot;code&quot;&gt;private&lt;/span&gt; deklariert werden.
&lt;/p&gt;

&lt;h4&gt;Proxy-Klasse&lt;/h4&gt;

&lt;p&gt;
Wozu dient eigentlich die Proxy-Klasse? Warum wird nicht direkt eine Referenz auf das Modul
in die Klasse eingefügt? Wozu der Umweg über die Proxy-Klasse?
&lt;/p&gt;
&lt;p&gt;
Die Proxy-Klasse ist notwendig, da von Modulen keine Instanzen erzeugt werden können.
Dennoch möchte man eventuell Instanzvariablen von Modulen nutzen. 
&lt;/p&gt;
&lt;p&gt;
Inkludieren die Klassen &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; und &lt;span class=&quot;code&quot;&gt;B&lt;/span&gt; das Modul &lt;span class=&quot;code&quot;&gt;M1&lt;/span&gt;, so darf die Änderung einer Instanzvariablen 
in der Klasse &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; nicht den Wert in &lt;span class=&quot;code&quot;&gt;B&lt;/span&gt; beeinflussen. Daher gibt für &lt;span class=&quot;code&quot;&gt;A&lt;/span&gt; und &lt;span class=&quot;code&quot;&gt;B&lt;/span&gt; jeweils eine 
Proxy-Klasse und die die Werte hält. 
&lt;/p&gt;
&lt;p&gt;
Alle Proxy-Klasse verweisen auf dasselbe Modul, daher werden Änderung an Methoden des Moduls 
in alle Klassen sichtbar: 
&lt;/p&gt;

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby source_ruby_rails&quot;&gt;&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo=&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby&quot;&gt;@&lt;/span&gt;foo&lt;/span&gt; &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; v
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
  
  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;M#foo: &lt;span class=&quot;source source_ruby source_ruby_embedded source_ruby_embedded_source&quot;&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby&quot;&gt;@&lt;/span&gt;foo&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;A&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M&lt;/span&gt;
  &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;variable variable_language variable_language_ruby&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; v
  &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt; 
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;B&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;include&lt;/span&gt; &lt;span class=&quot;variable variable_other variable_other_constant variable_other_constant_ruby&quot;&gt;M&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_with-arguments meta_function_method_with-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;variable variable_parameter variable_parameter_function variable_parameter_function_ruby&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_parameters punctuation_definition_parameters_ruby&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;variable variable_language variable_language_ruby&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; v
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt; 
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

a &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;A&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;47&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
p a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;M#foo 47&quot;
&lt;/span&gt;b &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
p b&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;M#foo 11&quot;
&lt;/span&gt;
&lt;span class=&quot;meta meta_module meta_module_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_module keyword_control_module_ruby&quot;&gt;module&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_module entity_name_type_module_ruby&quot;&gt;M&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;meta meta_function meta_function_method meta_function_method_without-arguments meta_function_method_without-arguments_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_def keyword_control_def_ruby&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_function entity_name_function_ruby&quot;&gt;foo&lt;/span&gt;&lt;/span&gt;
   &lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;modified M#foo &lt;span class=&quot;source source_ruby source_ruby_embedded source_ruby_embedded_source&quot;&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;variable variable_other variable_other_readwrite variable_other_readwrite_instance variable_other_readwrite_instance_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_variable punctuation_definition_variable_ruby&quot;&gt;@&lt;/span&gt;foo&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_embedded punctuation_section_embedded_ruby&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;
 &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;

p a&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;modified M#foo 47&quot;
&lt;/span&gt;p b&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;foo &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; &quot;modified M#foo 11&quot;
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Hoffe, ich habe für mehr Klarheit sorgen können und nicht mehr verwirrt :)
&lt;/p&gt;

&lt;p&gt;
to be continued ...
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-09-13:42</id>
    <published>2009-09-13T16:57:00Z</published>
    <updated>2009-09-13T16:57:58Z</updated>
    <category term="Konferenz"/>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="konferenz"/>
    <category term="rails"/>
    <category term="rails-konferenz"/>
    <category term="rk09"/>
    <category term="ruby"/>
    <link href="http://www.thomasbaustert.de/blog/2009/9/13/rails-konferenz-2009-review" rel="alternate" type="text/html"/>
    <title>Rails-Konferenz 2009 Review</title>
<content type="html">
            &lt;a href=&quot;http://www.rails-konferenz.de&quot;&gt;
&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2009/3/15/railskonferenz-logo-125.png&quot; /&gt;
&lt;/a&gt;

&lt;p&gt;
Ist schon wieder zwei Wochen her, dass wir die 4. &lt;a href=&quot;http://www.rails-konferenz.de&quot;&gt;Rails-Konferenz&lt;/a&gt; hinter uns gebracht haben. 
&lt;/p&gt;
&lt;p&gt;
Diesmal fand die Konferenz im &lt;a href=&quot;http://www.achat-hotel.de/wDeutsch/02_hotels/Uebersicht_Hotels/21_Uebersicht.php&quot;&gt;ACHAT Plaza Frankfurt/Offenbach&lt;/a&gt; statt. Das Hotel machte einen durchweg guten Eindruck, liegt allerdings verkehrstechnisch nicht besonders günstig. Auch der Vorraum für Pausen ist für 100+ Personen einfach viel zu klein. Die Zimmer waren sauber und geräumig und das Essen gut.
Für 2010 werden wir uns aber trotzdem nach einer Alternative umschauen. Wer Tipps hat, bitte melden.
&lt;/p&gt;
&lt;p&gt;
Den Gesprächen und Feedback-Bögen zur Folge, ist die Konferenz auch diese Jahr wieder sehr gut angekommen.
Die Workshops, Vorträge und das Socializing zwischendurch ergaben ein rundes Bild.
&lt;/p&gt;
&lt;p&gt;
Nur der Ort des Vorabend-Events kam nicht so gut an, weil die Teilnehmer vom Hotel in Offenbach erst in die Innenstadt von Frankfurt mussten. Das ACHAT-Hotel selbst wäre ein guter Ort gewesen, kostete aber zu viel Geld. Die Lounge im &lt;a href=&quot;http://www.flemings-hotels.com/de/club_frankfurt_city_flemings&quot;&gt;Fleming's Club&lt;/a&gt; kam bei den Anwesenden dann aber gut an. Danke auf diesem Wege nochmals an &lt;a href=&quot;http://www.xing.com&quot;&gt;XING&lt;/a&gt; für das Sponsoring und die Vorträge!
&lt;/p&gt;
&lt;p&gt;
Danke auch an alle Sponsoren, Speaker und Teilnehmer!!!
&lt;/p&gt;
&lt;p&gt;
Dem Feedback nach zu urteilen, werden auch 2010 wieder genügend Teilnehmer kommen. In diesem Sinne: bis 2010!. 
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-08-10:37</id>
    <published>2009-08-10T06:33:00Z</published>
    <updated>2009-08-10T06:33:52Z</updated>
    <category term="Konferenz"/>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="konferenz"/>
    <category term="rails"/>
    <category term="rails-konferenz"/>
    <link href="http://www.thomasbaustert.de/blog/2009/8/10/ticket-rabatt-auf-rubyonrails-de" rel="alternate" type="text/html"/>
    <title>Ticket-Rabatt auf rubyonrails.de</title>
<content type="html">
            Auf der Seite &lt;a href=&quot;http://www.rubyonrails.de&quot;&gt;rubyonrails.de&lt;/a&gt; von Kaan Karaca gibt es ab heute 20 Tickets für die &lt;a href=&quot;http://www.rails-konferenz.de&quot;&gt;Rails-Konferenz.de 2009&lt;/a&gt; mit einem Rabatt von 10%.
&lt;p&gt;
Na, dann mal schnell zuschlagen :)
&lt;/p&gt;
&lt;p&gt;
Vielen Dank an Kaan für die Unterstützung!
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-08-07:36</id>
    <published>2009-08-07T10:07:00Z</published>
    <updated>2009-08-07T10:07:39Z</updated>
    <category term="Plugins"/>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="plugin"/>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://www.thomasbaustert.de/blog/2009/8/7/rails-plugin-amount_field" rel="alternate" type="text/html"/>
    <title>Rails Plugin amount_field</title>
<content type="html">
            Ich habe heute mein Rails Plugin &lt;a href=&quot;http://github.com/thomasbaustert/amount_field/tree/master&quot;&gt;amount_field&lt;/a&gt; veröffentlicht. Es ermöglicht die Angabe von Beträgen im deutschen und im amerikanischen Format in Textfeldern eines Formulars, zum Beispiel:

&lt;p&gt;
&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2009/8/7/Bild_2.png&quot; /&gt;
&lt;img src=&quot;http://thomasbaustert.de/blog/assets/2009/8/7/Bild_1.png&quot; /&gt;
&lt;/p&gt;

Bisher habe ich das für den Einzelfall speziell gelöst. In einen aktuellen Projekt habe ich jedoch ein Formular mit vielen Beträgen, die im deutschen Format angezeigt und akzeptiert werden sollen. Daher war es an der Zeit, eine generelle Lösung zu finden. 

&lt;p&gt;
Da ich nichts adäquates an Gems oder Plugins gefunden habe, habe ich mich selbst daran gemacht. Und das war anfangs gar nicht so einfach :)
&lt;/p&gt;

&lt;p&gt;
Es ist die Eingabe (die Übertragung aus dem Formular an die Rails-Anwendung) und die korrekt formatierte Ausgabe (Anzeige im View/Formular) zu betrachten.
&lt;/p&gt;

&lt;h4&gt;Eingabe&lt;/h4&gt;

Vorweg folgende Definition:

&lt;ul&gt;
&lt;li&gt;Formatvalidierung: z.B. ist &quot;1.234,56&quot; ein gültiges Format?&lt;/li&gt;
&lt;li&gt;Wertvalidierung: z.B. ist 1.234,56 &gt; 1250 ?&lt;/li&gt;
&lt;/ul&gt;

Folgende Anforderungen und Überlegungen führten zur Lösung:

&lt;ol&gt;
&lt;li&gt;Damit sichergestellt werden kann, dass der eingegebene Wert wirklich ein gültiges Format hat (z.B. 1.234,56), muss zunächst eine Formatvalidierung erfolgen und danach die (sichere) Konvertierung in eine Zahl 1234.56. Im Anschluss kann optional die Wertvalidierung erfolgen.
&lt;p&gt;
Ohne die Formatvalidierung würde Rails aus 1.234,56 den Wert 1.23 machen, ohne dass der Anwender das gegebenenfalls merkt. Und das ist schlecht. 
&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;
Die Formatierung (Ein- und Ausgabe) hat eigentlich nichts mit dem Attribut oder dem ActiveRecord-Modell zu tun. Es handelt sich ja mehr um eine bestimmte Repräsentation eines Betrags und dafür ist das Modell nicht zuständig. Zur formatierten Anzeige werden u.a. die View-Helper von Rails genutzt.
&lt;p&gt;
Die Konvertierung von &quot;1.234,56&quot; in 1234.56 kann aber nicht auf Controller/View-Ebene erfolgen, da die Validierung der Attribute in ActiveRecord geschieht. Und die Formatvalidierung ist eben eine solche Validierung. Daher bleibt doch nur das Modell.
&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;Die Zuweisung als Ruby-Zahl an den Setter (an das Attribute) muss weiterhin wie gewohnt möglich sein:
&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby&quot;&gt;p &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;
p&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;string string_quoted string_quoted_single string_quoted_single_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;'&lt;/span&gt;12.345,67&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; schlecht
&lt;/span&gt;p&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;12345.67&lt;/span&gt;    &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; ok
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;li&gt;Der Getter des Attributs muss den Wert als (Ruby-)Zahl liefern, damit Berechnungen weiterhin wie gewohnt möglich sind:
&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby&quot;&gt;p &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;support support_class support_class_ruby&quot;&gt;Product&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;keyword keyword_other keyword_other_special-method keyword_other_special-method_ruby&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;constant constant_other constant_other_symbol constant_other_symbol_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby&quot;&gt;:&lt;/span&gt;price&lt;/span&gt; &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_key-value&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;1.23&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_section punctuation_section_function punctuation_section_function_ruby&quot;&gt;)&lt;/span&gt;
p&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;comment comment_line comment_line_number-sign comment_line_number-sign_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_comment punctuation_definition_comment_ruby&quot;&gt;#&lt;/span&gt; =&amp;gt; 1.23 damit Rechnen möglich
&lt;/span&gt;tax &lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt; p&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;.&lt;/span&gt;price &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;19.0&lt;/span&gt; &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;constant constant_numeric constant_numeric_ruby&quot;&gt;100.0&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;/li&gt;

&lt;li&gt;
Eine clientseitige Formatvalidierung  (und Formatierung) durch JavaScript ist hilfreich, verhindet aber nicht unbedingt die Übertragung falsch formatierter Beträge und daher ist eine serverseitige Formatvalidierung immer notwendig.
&lt;/li&gt;
&lt;br /&gt;

&lt;li&gt;Die Formatierung eines Betrags besteht immer aus den drei Werten: 

&lt;ul&gt;
&lt;li&gt;Separator (Tausendseparator)&lt;/li&gt;
&lt;li&gt;Delimiter (Trennung Ganzzahl und Nachkommastellen)&lt;/li&gt;
&lt;li&gt;Precision (Anzahl der Nachkommastellen)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
Die drei Werte bilden die Formatkonfiguration: 
&lt;br /&gt;deutsch: &lt;code&gt;{ :precision =&gt; 2, :delimiter =&gt; '.', :separator =&gt; ',' }&lt;/code&gt; 
&lt;br /&gt;amerikanisch:&lt;code&gt;{ :precision =&gt; 2, :delimiter =&gt; ',', :separator =&gt; '.' }&lt;/code&gt;
&lt;/p&gt;
&lt;/li&gt;

&lt;li&gt;Fehlermeldungen bei einen falschen Format sollten internationalisierbar sein&lt;/li&gt;
&lt;br /&gt;

&lt;li&gt;Hinweis: Active Record speichert den übergebenen Wert “1.234,56” in dem Attribute &quot;price&quot;. Erst beim Lesen des Wertes wird dieser konvertiert zurückgeliefert. Daher liefert &quot;price_before_type_cast&quot; den Wert “1.234,56” und &quot;price&quot; den Wert 1.234 zurück. Die Wertvalidierung erfolgt bei Active Record auf Basis von XXX_before_type_cast.
&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;
Als Lösung definiere ich einen eigenen View-Helper &quot;amount_field&quot; als Ersatz für &quot;text_field&quot;. Das HTML sieht wie folgt aus:

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;&amp;lt;&lt;/span&gt;input name&lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt;product[amount_field_price]&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_assignment keyword_operator_assignment_ruby&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;string string_quoted string_quoted_double string_quoted_double_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_begin punctuation_definition_string_begin_ruby&quot;&gt;&quot;&lt;/span&gt; amount_field&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_string punctuation_definition_string_end punctuation_definition_string_end_ruby&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;punctuation punctuation_separator punctuation_separator_method punctuation_separator_method_ruby&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;keyword keyword_operator keyword_operator_arithmetic keyword_operator_arithmetic_ruby&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;keyword keyword_operator keyword_operator_comparison keyword_operator_comparison_ruby&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;
&lt;/p&gt;

&lt;p&gt;
Der eingegebene Wert (z.B. &quot;1.234,56&quot;) wird dadurch über den Parameter &lt;code&gt;amount_field_price&lt;/code&gt; und nicht (wie normalerweise) über den Parameter &lt;code&gt;price&lt;/code&gt; übertragen.
&lt;/p&gt;

&lt;p&gt;
Zusätzlich existiert das Validierungsmakro &quot;validates_amount_format_of&quot;, dass für jedes angegebene Attribut eine spezielle Setter-Methode (z.B. &lt;code&gt;amount_field_price=(value)&lt;/code&gt; definiert, die den Parameter &lt;code&gt;amount_field_price&lt;/code&gt; annimmt und Werte im Format &quot;1.234,56&quot; akzeptiert.

&lt;pre class=&quot;textmate-source mac_classic&quot;&gt;&lt;span class=&quot;source source_ruby&quot;&gt;&lt;span class=&quot;meta meta_class meta_class_ruby&quot;&gt;&lt;span class=&quot;keyword keyword_control keyword_control_class keyword_control_class_ruby&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;entity entity_name entity_name_type entity_name_type_class entity_name_type_class_ruby&quot;&gt;Product&lt;span class=&quot;entity entity_other entity_other_inherited-class entity_other_inherited-class_ruby&quot;&gt; &lt;span class=&quot;punctuation punctuation_separator punctuation_separator_inheritance punctuation_separator_inheritance_ruby&quot;&gt;&amp;lt;&lt;/span&gt; ActiveRecord::Base&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  validates_amount_format_of &lt;span class=&quot;constant constant_other constant_other_symbol constant_other_symbol_ruby&quot;&gt;&lt;span class=&quot;punctuation punctuation_definition punctuation_definition_constant punctuation_definition_constant_ruby&quot;&gt;:&lt;/span&gt;price&lt;/span&gt; 
&lt;span class=&quot;keyword keyword_control keyword_control_ruby&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;

&lt;/p&gt;

&lt;p&gt;
Nach der Validierung und Konvertierung (z.B. &quot;1.234,56&quot; in 1234.56) wird der Wert an das Originalattribut &quot;price&quot; zugewiesen und kann von weiteren Validierungsmakro geprüft werden (z.B: &lt;code&gt;validates_numericality_of :price&lt;/code&gt;). 
&lt;/p&gt;

&lt;h4&gt;Ausgabe&lt;/h4&gt;

&lt;p&gt;
Damit die Ausgabe des Wertes 1234.56 formatiert erfolgt (z.B. &quot;1.234,56&quot;), verwendet der View-Helper &lt;code&gt;amount_field&lt;/code&gt; intern den View-Helper &lt;code&gt;number_with_precision&lt;/code&gt; mit der global definierten Formatkonfiguration. Im Fehlerfall wird der Wert nicht formatiert, sondern wie eingegeben angezeigt. 
&lt;/p&gt;

&lt;p&gt;
Das Gem (oder Plugin) inklusive Dokumentation ist unter &lt;a href=&quot;http://github.com/thomasbaustert/amount_field/tree/master&quot;&gt;GitHub&lt;/a&gt; zu finden.
&lt;/p&gt;

&lt;p&gt;
Freue mich über Feedback, Fragen oder Fehlermeldungen.
&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-07-22:30</id>
    <published>2009-07-22T19:10:00Z</published>
    <updated>2009-08-07T08:07:52Z</updated>
    <category term="Konferenz"/>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="konferenz"/>
    <category term="rails"/>
    <category term="rails-konferenz"/>
    <link href="http://www.thomasbaustert.de/blog/2009/7/22/anmeldung-zur-rails-konferenz-de-2009-online" rel="alternate" type="text/html"/>
    <title>Anmeldung zur Rails-Konferenz.de 2009 online! </title>
<content type="html">
            Die &lt;a href=&quot;http://anmeldung.rails-konferenz.de&quot;&gt;Anmeldung&lt;/a&gt; zur &lt;a href=&quot;http://rails-konferenz.de&quot;&gt;Rails-Konferenz.de 2009&lt;/a&gt; ist online! 

&lt;p&gt;Wir sehen uns in Frankfurt/Offenbach!&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://www.thomasbaustert.de/blog/">
    <author>
      <name>thomas</name>
    </author>
    <id>tag:www.thomasbaustert.de,2009-07-20:28</id>
    <published>2009-07-20T08:53:00Z</published>
    <updated>2009-08-07T08:07:37Z</updated>
    <category term="Konferenz"/>
    <category term="Rails"/>
    <category term="Ruby"/>
    <category term="konferenz"/>
    <category term="rails"/>
    <category term="rails-konferenz.de"/>
    <link href="http://www.thomasbaustert.de/blog/2009/7/20/programm-rails-konferenz-2009-online" rel="alternate" type="text/html"/>
    <title>Programm Rails-Konferenz 2009 online</title>
<content type="html">
            Das Programm zur &lt;a href=&quot;http://rails-konferenz.de&quot;&gt;Rails-Konferenz 2009&lt;/a&gt; ist jetzt online. Wir haben wieder einen bunten Mix aus den vielen Proposals erstellt und hoffen auf viele Teilnehmer und eine tolle Konferenz, wie in den letzten Jahren.
          </content>  </entry>
</feed>

