tag:www.stefanwienert.net,2008:/railsRails - Stefan Wienert's Blog2011-09-01T18:13:03ZEnkiStefan Wienertstwienert@gmail.comtag:www.stefanwienert.net,2008:Post/472010-05-26T13:42:00Z2010-05-26T15:42:42ZRuby on Rails Screencast - Implementation einer User Anmeldung<p>Für eine kommende Vorlesung über Test Driven Development habe ich einen Screencast angefertigt.</p>
<p>Das ganze natürlich in Rails mit Test::Unit und Vim (wegen der Sparsamkeit mit dem Screenplatz).</p>
<p>Das Auditorium kennt Rails größtenteils nicht, weshalb es ein einfach gewähltes Beispiel ist:<br />
Die Implementierung eines simplen Authentifizierungsmechanismus, der einen Nutzer am System anmeldet.</p>
<p><object width="400" height="300"><param name="allowfullscreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=12044362&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=12044362&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"></embed></object><p><a href="http://vimeo.com/12044362">Screencast Rails Session Authentication</a> from <a href="http://vimeo.com/user3902285">Stefan Wienert</a> on <a href="http://vimeo.com">Vimeo</a>.</p></p>
<p>Das genutzte Programm zur Aufnahme war Xvidcap. Sehr genial.</p>tag:www.stefanwienert.net,2008:Post/422010-04-07T02:48:00Z2010-04-07T04:48:15ZMal wieder ein paar Links zum Thema Rails und Vim<p>Vim:</p>
<ul>
<li><a href="http://robots.thoughtbot.com/post/166073596/intro-rails-vim">Rails.vim</a></li>
<li><a href="http://vimcasts.org/">Qualitativ hochwertiger Screencast für <span class="caps">VIM</span></a></li>
</ul>
<p>Rails:</p>
<ul>
<li><a href="http://blog.siverti.com.br/gmate/">Gmate – Ein Gedit Plugin Kompendium</a> sehr genial auch für nicht-Rails Projekte</li>
<li><a href="http://www.youtube.com/rhomobile#p/a/f/0/T2pztOky_L0">plattformübergreifend Android, iPhone, WinMob Anwendungein in einem Rails ähnlichen Framework bauen</a></li>
<li><a href="http://eggsonbread.com/2010/03/28/my-rspec-best-practices-and-tips/">Rspec Best Practices</a></li>
<li><a href="http://rubybestpractices.com/">Kostenloses Beta Buch: Ruby Best Practices</a></li>
<li><a href="http://www.ruby-toolbox.com/">Rubytoolbox – Auswahl und Kategorisierung der beliebtesten Gems</a></li>
<li><a href="http://www.rubyflow.com/">Rubyflow – <span class="caps">DER</span> Rubyticker</a> Dazu hier von <a href="http://site.stefanwienert.net/rss/rubyflow.rss">mir der komplette Feed inklusive der nicht-approved Beiträge</a></li>
</ul>tag:www.stefanwienert.net,2008:Post/412010-03-23T16:40:00Z2010-03-23T17:40:58ZUmstellung auf "www.stefanwienert.net" und Passenger mit apache mod userdir<p>Diejenigen, die meinen Feed abonniert haben, haben es wahrscheinlich schon gemerkt, da die ganzen Items als ungelesen markiert sein könnten.<br />
Da ich passenger verwende, aber gleichzeitig noch apache mit mod_userdir nutzen möchte, blieb mir nichts anderes übrig als den Hauptteil der Site auf eine Subdomain zu legen. Aus irgendwelchen unerfindlichen Gründen hatte ich damals “site.stefanwienert.net” genommen. Jetzt ist mir mal aufgefallen, dass die Wahl der Subdomain “www.” deutlich klüger gewesen wäre.</p>
<p>Anfragen an <b>mod_userdir</b> können bei dieser Methode dann einfach durch “http://hauptdomain/~username” entgegengenommen werden. Die Haupt Rails Domain, auf die der Nutzer bei Erstkontakt stoßen sollte, ist dann “www.stefanwienert.net” und wird dank Passenger dann an einen Ruby-Prozess dispatcht. Dazu muss man einfach nur zwei vhosts in seiner “/etc/apache2/sites-enabled/…” aktivieren:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># Hier fuer die Hauptdomain, um weitere Websites zu ermoeglichen</span><tt>
</tt><span class="c"># z.B. php Wikis oder Userspaces</span><tt>
</tt><<span class="co">VirtualHost</span> *:<span class="i">80</span>> <tt>
</tt> <span class="co">ServerAdmin</span> s59605<span class="iv">@htw</span>-dresden.de <tt>
</tt> <span class="co">ServerName</span> stefanwienert.net <tt>
</tt> <span class="co">DocumentRoot</span> <span class="rx"><span class="dl">/</span><span class="k">var</span><span class="dl">/</span></span>www <tt>
</tt><span class="c"># PassengerHighPerformance on </span><tt>
</tt> <<span class="co">Directory</span> <span class="rx"><span class="dl">/</span><span class="k">var</span><span class="dl">/</span></span>www/> <tt>
</tt> <span class="co">Options</span> <span class="co">Indexes</span> <span class="co">FollowSymLinks</span> <span class="co">MultiViews</span><tt>
</tt> <span class="co">AllowOverride</span> <span class="co">All</span> <tt>
</tt> <span class="co">Order</span> allow,deny <tt>
</tt> allow from all <tt>
</tt> <<span class="rx"><span class="dl">/</span><span class="k">Directory> <tt>
</tt><</span><span class="dl">/</span></span><span class="co">VirtualHost</span>> <tt>
</tt><tt>
</tt><span class="c"># jetzt der eigentliche Rails Prozess</span><tt>
</tt><<span class="co">VirtualHost</span> *:<span class="i">80</span>> <tt>
</tt> <span class="co">ServerAdmin</span> info<span class="iv">@stefanwienert</span>.net <tt>
</tt> <span class="co">ServerName</span> www.stefanwienert.net <tt>
</tt> <span class="co">ServerAlias</span> site.stefanwienert.net <tt>
</tt> <span class="c">#RailsBaseURI /site </span><tt>
</tt> <span class="co">DocumentRoot</span> <span class="rx"><span class="dl">/</span><span class="k">path</span><span class="dl">/</span></span>to/rails/public <tt>
</tt><span class="c"># gzip html, css and js </span><tt>
</tt> <span class="co">AddOutputFilterByType</span> <span class="co">DEFLATE</span> text/html text/css application/x-javascript application/javascript<tt>
</tt><tt>
</tt> <<span class="co">Directory</span> <span class="rx"><span class="dl">/</span><span class="k">path</span><span class="dl">/</span></span>to/rails/public> <tt>
</tt> <span class="co">Order</span> allow,deny <tt>
</tt> <span class="co">Allow</span> from all <tt>
</tt> <span class="co">AllowOverride</span> <span class="co">All</span> <tt>
</tt> <<span class="rx"><span class="dl">/</span><span class="k">Directory> <tt>
</tt><</span><span class="dl">/</span></span><span class="co">VirtualHost</span>><tt>
</tt><tt>
</tt></pre></td>
</tr></table>
<p>Zu guter Letzt noch eine 304 Weiterleitung für die, die “http://site.stefanwienert.net” oder “http://stefanwienert.net” eintippen. Das ganze kann man in die entsprechenden htaccess packen oder oben gleich mit bei den “Directory” Direktiven mit angeben. Hier der Vollständigkeit halber, bevor ihr selbst erst googlen müsst.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># /var/www/.htaccess:</span><tt>
</tt><span class="co">RewriteEngine</span> <span class="co">On</span><tt>
</tt><tt>
</tt><span class="co">RewriteCond</span> <span class="s"><span class="dl">%{</span><span class="k">HTTP_HOST</span><span class="dl">}</span></span> ^stefanwienert.net<span class="er">$</span><tt>
</tt><span class="co">RewriteCond</span> <span class="s"><span class="dl">%{</span><span class="k">REQUEST_URI</span><span class="dl">}</span></span> ^<span class="er">\</span><span class="rx"><span class="dl">/</span><span class="k">$<tt>
</tt>RewriteRule ^(.*)$ http:</span><span class="dl">/</span></span>/www.stefanwienert.net/<span class="gv">$1</span> [<span class="co">R</span>=permanent,<span class="co">L</span>]<tt>
</tt><tt>
</tt><tt>
</tt><span class="c"># /path/to/rails/public/.htaccess</span><tt>
</tt><span class="co">RewriteEngine</span> on<tt>
</tt><tt>
</tt><span class="co">RewriteCond</span> <span class="s"><span class="dl">%{</span><span class="k">HTTP_HOST</span><span class="dl">}</span></span> ^site.stefanwienert.net [<span class="co">NC</span>]<tt>
</tt><span class="co">RewriteRule</span> ^(.*)<span class="er">$</span> http<span class="sy">:/</span>/www.stefanwienert.net/<span class="gv">$1</span> [<span class="co">L</span>,<span class="co">R</span>=<span class="i">301</span>]<tt>
</tt><tt>
</tt><tt>
</tt><span class="c"># Hups, hier sieht man mal, dass ich die Zeilen jeweils woanders</span><tt>
</tt><span class="c"># herkopiert habe: Selbe Funktion aber etwas andere Syntax :)</span><tt>
</tt></pre></td>
</tr></table>
tag:www.stefanwienert.net,2008:Post/392010-03-22T07:07:00Z2010-03-22T08:07:16ZVim 7.2 mit ERB HAML .. Syntaxhightlighting auf Debian Squeeze <p>Wer sein Rails Projekt auf Debian laufen hat, und seine Minichanges mit <span class="caps">VIM</span> macht, der kennt vielleicht das Problem, dass bei Vim 7.1 keine Syntax Beschreibungen fuer <span class="caps">ERB</span> und <span class="caps">HAML</span> (z.B.) dabei sind.</p>
<p>7.2. kann man wie folgt installieren (Alternativ aber auch aus der Quelle, hier jetzt mit den debs)</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="c"># Pakete herunterladen</span><tt>
</tt>wget http<span class="sy">:/</span>/ftp.de.debian.org/debian/pool/main/v/vim/vim-common_7.<span class="fl">2.330</span>-<span class="i">1</span>_i386.deb<tt>
</tt>wget http<span class="sy">:/</span>/ftp.de.debian.org/debian/pool/main/v/vim/vim-runtime_7.<span class="fl">2.330</span>-<span class="i">1</span>_all.deb<tt>
</tt>wget http<span class="sy">:/</span>/ftp.de.debian.org/debian/pool/main/v/vim/vim_7.<span class="fl">2.330</span>-<span class="i">1</span>_i386.deb <tt>
</tt><tt>
</tt><span class="c"># Das Zeug installieren</span><tt>
</tt>dpkg -i *.deb<tt>
</tt></pre></td>
</tr></table>
<p>Jetzt ist es zwar schon installiert, aber u.a. das Syntaxhighlighting sollte noch etwas bocken, weil noch der runtimepath angepasst werden muss:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">vim /usr/share/vim/vimrc<tt>
</tt><tt>
</tt># Dort unten einfuegen, falls die Zeile in der Datei nicht vorhanden ist:<tt>
</tt>set runtimepath=~/.vim,/etc/vim,/usr/share/vim/vimfiles,/usr/share/vim/addons,/usr/share/vim/vim72,\<tt>
</tt> /usr/share/vim/vimfiles,/usr/share/vim/addons/after,~/.vim/after<tt>
</tt><tt>
</tt># Speichern und raus<tt>
</tt></pre></td>
</tr></table>
<p>Sollte soweit klappen. Bitte einen Kommentar hinterlassen, falls was schiefgelaufen ist.</p>tag:www.stefanwienert.net,2008:Post/372010-03-02T06:31:00Z2011-09-01T18:13:03ZRails/Passenger im Parallels Plesk zum Laufen bekommen EDIT mit SSL<p>Wer auch Parallels Plesk Panel für seine Serveradministration verwendet, und sich schonmal gefragt hat, ob es was besseres als die Build-in Fast <span class="caps">CGI</span> Unterstützung oder Mongrel/Webrick gibt, dem will ich hier mal einen kleinen Guide geben, wie das ganze mit Passenger zu bewerkstelligen ist.<br />
Wir verwenden für die Administration unserer Server auch Plesk, da es echt stupid simple ist.</p>
<p>Ich gehe davon aus, dass Ruby und Rubygems bereits installiert sind! (Sollte man z.B. Debian verwenden, auf keinen Fall die Pakete aus dem apt-get installieren, sondern <a href="http://rubyonrails.org/download">manuell wie hier beschreiben</a>.) Auch ein Root-Zugang zum Server wird benötigt.</p>
<p>Also:</p>
<ol>
<li>im Plesk eine neue Domain/Subdomain anlegen</li>
<li>Unser Rails-Projekt nach <tt>/var/www/vhosts/<span class="caps">DOMAIN</span>/httpdocs</tt> bzw. <tt>/var/www/vhosts/<span class="caps">DOMAIN</span>/subdomains/<span class="caps">SUBDOMAIN</span>/httpdocs</tt> kopieren. Also genau dort rein, kein weiteres Unterverzeichnis (nach httpdocs kommen dann gleich app db config public …)</li>
<li>Schauen, dass die Lese/Schreibrechte hinhauen: z.B. <tt>chgrp psaserv log db tmp -R && chmod g+w * -R</tt>. Im einzelnen mal schauen.</li>
<li>Root Konsole: Gems installieren und Datenbank migrieren:</li>
</ol><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">rake gems<span class="sy">:install</span><tt>
</tt>rake db<span class="sy">:migrate</span> <span class="co">RAILS_ENV</span>=<span class="s"><span class="dl">"</span><span class="k">production</span><span class="dl">"</span></span><tt>
</tt>gem install passenger<tt>
</tt><span class="c"># laengere Anleitung befolgen. Im Endeffekt muss man ein paar Zeilen in die apache2.conf kopieren. </span><tt>
</tt><span class="c"># Den zweiten Teil mit mit der Vserver Konfiguration interessiert uns im Moment nicht</span><tt>
</tt></pre></td>
</tr></table>
<ol>
<li>Im Ordner <tt><span class="caps">DOMAIN</span>/conf</tt> also von unserem httpdocs Verzeichnis <tt>../conf/vhost.conf</tt> nun die Datei vhost.conf anlegen und folgendes reinkopieren (jeweils das richtige Verzeichnis als Ziel nehmen, je nachdem ob wir eine Subdomain oder Domain benutzen möchten):</li>
</ol><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"> <span class="co">DocumentRoot</span> <span class="rx"><span class="dl">/</span><span class="k">var</span><span class="dl">/</span></span>www/vhosts/<span class="co">DOMAIN</span>/httpdocs/public<tt>
</tt><span class="c"># bzw. /var/www/vhosts/DOMAIN/subdomains/SUBDOMAIN/httpdocs/public</span><tt>
</tt> <<span class="co">Directory</span> <span class="rx"><span class="dl">/</span><span class="k">var</span><span class="dl">/</span></span>www/vhosts/pludoni.de/subdomains/tasks/httpdocs/public ><tt>
</tt> <span class="co">AllowOverride</span> all<tt>
</tt> <span class="co">Options</span> -<span class="co">MultiViews</span><tt>
</tt> <<span class="rx"><span class="dl">/</span><span class="k">Directory><tt>
</tt></span></span></pre></td>
</tr></table>
<ol>
<li>plesk Vhost reloaden:</li>
</ol><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">/usr/local/psa/admin/sbin/websrvmng -u --vhost-name=DOMAIN.de<tt>
</tt></pre></td>
</tr></table>
<p>hierbei jeweils immer nur die Domain angeben, auch wenn wir nur einen Subdomain anlegen.</p>
<p>Nun sollte unsere Rails App unter der Domain bzw. Subdomain verfügbar sein. Neustarten können wir Passenger indem wir ein <tt>touch tmp/restart.txt</tt> oder die Datei sonst irgendwie im Timestamp verändern.</p>
<p><strong>Edit</strong>: Möchte man Plesk, Rails und Passenger mit <span class="caps">SSL</span> verwenden (also https://…domain), muss man noch etwas tun:</p>
<ul>
<li>die Datei “conf/vhost.conf” nach “conf/vhost_ssl.conf” kopieren</li>
<li>Plesk reloaden</li>
</ul>
<p>Ansonsten erhält man ein 403 “Forbidden You don’t have permission to access / on this server.”, da Apache das ganze als statische <span class="caps">HTML</span>-Seite betrachtet, und die index.html sucht.</p>tag:www.stefanwienert.net,2008:Post/362010-02-28T19:13:00Z2010-02-28T20:13:44ZKurzes Gem Showcase - Delicious, actsasarchive, menu borwsercms css sprite<p>Ich schaue gerade meine kürzlich gebookmarkten Sites an, und will hier mal ein paar coole Ruby Ressourcen zeigen.</p>
<ul>
<li>Delicious-<span class="caps">API</span>: http://github.com/weppos/www-delicious für den beliebten Bookmarkdienst</li>
<li>Acts as archive, destroy und delete Aktionen eines Objektes führen nicht zur Löschung, sondern Archivierung http://github.com/winton/acts_as_archive</li>
<li>MMMenu http://github.com/snitko/mmmenu eine kleine Menü <acronym title="(Domain Specific Language"><span class="caps">DSL</span></acronym>)</li>
<li>Automatische, transparente <span class="caps">CSS</span> Sprite Transformation http://github.com/reevoo/spriter</li>
<li>BrowserCMS, meine Basis <span class="caps">CMS</span> für meine nächsten Projekte http://www.browsercms.org/ <br />
Schaut <a href="http://aac2009.confreaks.com/07-feb-2009-10-00-browsercms-patrick-peak-and-paul-barry.html">euch das Video dazu an</a></li>
</ul>
<p>und sowieso:<br />
http://www.ruby-toolbox.com/ und http://www.rubyflow.com/ zur Ideenfindung.</p>
<p>I love that community :)</p>tag:www.stefanwienert.net,2008:Post/262010-01-13T22:09:00Z2010-01-13T23:09:53ZUmgang und Mapping einer Legacy Datenbank mit Ruby (ohne Rails) mit abweichenenden Namenskonventionen mit Active Support<h3>Einleitung/Motivation</h3>
<p>Zur Zeit moechte ich verschiedene <span class="caps">XML</span>-Dialekte aus einem <strong>vorhandenen Datenbankschema</strong> gewinnen, und brauchte dazu ein ordentliches <strong>Objektrelationales Mapping,</strong> wie man es aus <strong>Rails</strong> ja kennt. (Ausprobieren! keine Zeile <span class="caps">SQL</span> mehr notwendig :D). <br />
Allerdings <strong>ohne Rails</strong> sondern in einem einfachen Rubyscript.<br />
Was es dort alles gibt, will ich hier mal kurz exemplarisch vorfuehren.</p>
<h3>Voraussetzung und Datenbankverbindung</h3>
<p>Um ein Legacy relationales Datenmodell mit Ruby schoen zu mappen, ging ich letztens wie folgt vor:</p>
<p>Zu erst Rails (<strong>active_record</strong> ist aber auch ausreichend) installieren, falls noch nicht gemacht (fuer active_record) und <strong>composite primary keys</strong>, das uns wie der Name schon sagt, <strong>zusammengesetzte Primärschlüssel</strong>, welches unser Legacy-Schema mitunter mit sich bringt, bereitstellt.</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">sudo gem install rails composite_primary_keys <tt>
</tt></pre></td>
</tr></table>
<p>Nun können wir uns im ersten Schritt <strong>mit unserer Datenbank verbinden</strong>:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">"</span><span class="k">rubygems</span><span class="dl">"</span></span><tt>
</tt>require <span class="s"><span class="dl">"</span><span class="k">active_record</span><span class="dl">"</span></span><tt>
</tt>require <span class="s"><span class="dl">"</span><span class="k">composite_primary_keys</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt>options = {<span class="sy">:adapter</span> => <span class="s"><span class="dl">'</span><span class="k">mysql</span><span class="dl">'</span></span>,<tt>
</tt> <span class="sy">:database</span> => <span class="s"><span class="dl">'</span><span class="k">databasename</span><span class="dl">'</span></span>,<tt>
</tt> <span class="sy">:username</span> => <span class="s"><span class="dl">'</span><span class="k">username</span><span class="dl">'</span></span>,<tt>
</tt> <span class="sy">:password</span> => <span class="s"><span class="dl">'</span><span class="k">******</span><span class="dl">'</span></span>,<tt>
</tt> <span class="sy">:host</span> => <span class="s"><span class="dl">'</span><span class="k">localhost</span><span class="dl">'</span></span> ,<tt>
</tt> <span class="sy">:encoding</span> => <span class="s"><span class="dl">'</span><span class="k">utf8</span><span class="dl">'</span></span>}<tt>
</tt><span class="co">ActiveRecord</span>::<span class="co">Base</span>.establish_connection(options)<tt>
</tt></pre></td>
</tr></table>
<h3>Definition der Modelle</h3>
<p>Nun kommt dort drunter die Konstruktion der <strong>Modell-Klassen</strong>, die die Tabellen abbilden.</p>
<p>Angenommen wir haben eine <b>Tags</b>, <b>Posts</b>, <b>Posts_Tags</b> und <b>Users</b> Tabelle (in freier Ruby Namenskonvention) mit den folgenden Beziehungen:<br />
Post : Tag = n : m (Jobs_Tags)<br />
Post : User = n : 1</p>
<p>Also ein Post hat eine Anzahl Tags (über “jobs_tags”) und genau einen User.</p>
<p>Da das aber zu leicht wäre, gibt es folgende <strong>Handicaps</strong> :):</p>
<ul>
<li>“Posts” Tabelle heißt “entries_import”, Primaerschluessel (PK) postid, Fremdschlüssel “uid” heißt “nutzer”</li>
<li>“Tags” Tabelle heißt “clouds_import”, PK tagid</li>
<li>“Posts_Tags” Tabelle heisst “clouds_import_lnk”, PK (postid,tagid) <strong>zusammengesetzter Primaerschluessel!</strong></li>
<li>“Users”-Tabelle heißt “users”, mit PK uid</li>
</ul>
<p>(leicht abgeändertes RealWorld Beispiel!)</p>
<p>Tja sieht schon recht messy aus. Aber alles machbar:</p>
<h3>Der Code</h3><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt>16<tt>
</tt>17<tt>
</tt>18<tt>
</tt>19<tt>
</tt><strong>20</strong><tt>
</tt>21<tt>
</tt>22<tt>
</tt>23<tt>
</tt>24<tt>
</tt>25<tt>
</tt>26<tt>
</tt>27<tt>
</tt>28<tt>
</tt>29<tt>
</tt><strong>30</strong><tt>
</tt>31<tt>
</tt>32<tt>
</tt>33<tt>
</tt>34<tt>
</tt>35<tt>
</tt>36<tt>
</tt>37<tt>
</tt>38<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">class</span> <span class="cl">Post</span> < <span class="co">ActiveRecord</span>::<span class="co">Base</span><tt>
</tt> set_table_name <span class="s"><span class="dl">"</span><span class="k">entries_import</span><span class="dl">"</span></span> <span class="c"># posts Tabelle</span><tt>
</tt> set_primary_key <span class="s"><span class="dl">"</span><span class="k">postid</span><span class="dl">"</span></span><tt>
</tt> has_many <span class="sy">:tags</span>, <span class="sy">:through</span> => <span class="sy">:taggings</span><tt>
</tt> has_many <span class="sy">:taggings</span>, <span class="sy">:primary_key</span> => <span class="s"><span class="dl">"</span><span class="k">postid</span><span class="dl">"</span></span>, <span class="sy">:foreign_key</span> => <span class="s"><span class="dl">"</span><span class="k">postid</span><span class="dl">"</span></span><tt>
</tt> belongs_to <span class="sy">:user</span>, <span class="sy">:foreign_key</span> => <span class="s"><span class="dl">"</span><span class="k">nutzer</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt><span class="c"># Extra Points! Unser 'Post' hat ein "visible" Attribut, welches </span><tt>
</tt><span class="c"># geradezu nach einem named scope schreit! :)</span><tt>
</tt> named_scope <span class="sy">:visible</span>, <span class="sy">:conditions</span> => {<span class="sy">:visible</span> => <span class="i">1</span>}, <span class="sy">:order</span> => <span class="s"><span class="dl">"</span><span class="k">pubDate desc</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt><tt>
</tt><span class="c">#Extra Points! Tags direkt als (Komma)getrennte Liste zurueckgeben lassen, und </span><tt>
</tt><span class="c"># noch den Tag "Blog" auf jeden Fall ans Ende der Tags haengen</span><tt>
</tt> <span class="r">def</span> <span class="fu">tag_list</span>(sep = <span class="s"><span class="dl">"</span><span class="k">,</span><span class="dl">"</span></span>)<tt>
</tt> (tags.map(&<span class="sy">:name</span>) << <span class="s"><span class="dl">"</span><span class="k">Blog</span><span class="dl">"</span></span>).uniq.join(sep)<tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="r">class</span> <span class="cl">Tag</span> < <span class="co">ActiveRecord</span>::<span class="co">Base</span><tt>
</tt> set_table_name <span class="s"><span class="dl">"</span><span class="k">clouds_import</span><span class="dl">"</span></span><tt>
</tt> set_primary_key <span class="s"><span class="dl">"</span><span class="k">tagid</span><span class="dl">"</span></span><tt>
</tt> has_many <span class="sy">:jobs</span>, <span class="sy">:through</span> => <span class="sy">:taggings</span><tt>
</tt> has_many <span class="sy">:taggings</span>, <span class="sy">:primary_key</span> => <span class="s"><span class="dl">"</span><span class="k">tagid</span><span class="dl">"</span></span>, <span class="sy">:foreign_key</span> => <span class="s"><span class="dl">"</span><span class="k">tagid</span><span class="dl">"</span></span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="r">class</span> <span class="cl">Tagging</span> < <span class="co">ActiveRecord</span>::<span class="co">Base</span><tt>
</tt> set_table_name <span class="s"><span class="dl">"</span><span class="k">clouds_import_lnk</span><span class="dl">"</span></span><tt>
</tt> set_primary_keys <span class="sy">:jobid</span>, <span class="sy">:tagid</span> <span class="c"># Zusammengesetzter Primaerschluessel</span><tt>
</tt> belongs_to <span class="sy">:job</span>, <span class="sy">:primary_key</span> => <span class="s"><span class="dl">"</span><span class="k">postid</span><span class="dl">"</span></span>, <span class="sy">:foreign_key</span> => <span class="s"><span class="dl">"</span><span class="k">postid</span><span class="dl">"</span></span><tt>
</tt> belongs_to <span class="sy">:tag</span>, <span class="sy">:primary_key</span> => <span class="s"><span class="dl">"</span><span class="k">tagid</span><span class="dl">"</span></span>, <span class="sy">:foreign_key</span> => <span class="s"><span class="dl">"</span><span class="k">tagid</span><span class="dl">"</span></span><tt>
</tt><span class="r">end</span><tt>
</tt><tt>
</tt><span class="r">class</span> <span class="cl">User</span> < <span class="co">ActiveRecord</span>::<span class="co">Base</span><tt>
</tt> set_primary_key <span class="s"><span class="dl">"</span><span class="k">uid</span><span class="dl">"</span></span><tt>
</tt> set_table_name <span class="s"><span class="dl">'</span><span class="k">users</span><span class="dl">'</span></span><tt>
</tt> has_many <span class="sy">:jobs</span>, <span class="sy">:foreign_key</span> => <span class="s"><span class="dl">"</span><span class="k">nutzer</span><span class="dl">"</span></span>, <span class="sy">:primary_key</span> => <span class="s"><span class="dl">"</span><span class="k">uid</span><span class="dl">"</span></span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
<p>Fertig!<br />
Nun können wir in althergebrachter Rails Manier extrem bequem auf unsere Modelle wie folgt zugreifen:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><tt>
</tt>posts = <span class="co">Post</span>.all<tt>
</tt>posts.first.tags <span class="c"># gibt uns die tags zurück</span><tt>
</tt>post = <span class="co">Post</span>.find(<span class="sy">:first</span>, <span class="sy">:order</span> => <span class="s"><span class="dl">"</span><span class="k">...</span><span class="dl">"</span></span>)<tt>
</tt>post.user.name<tt>
</tt><tt>
</tt><span class="c"># oder auch named scopes (siehe oben)</span><tt>
</tt><span class="co">Post</span>.visible.first.tag_list<tt>
</tt></pre></td>
</tr></table>
<p>usw. Wirklich eine Wohltat ;)</p>
<p>Natürlich kann man in seinen Modellen noch Methoden definieren, die uns den Zugriff noch erleichtern und unser Modell um Funktionalität erweitert und damit unsere Controller und Views nicht zumuellt.</p>
<h3>Bonus: <span class="caps">XML</span> Builder</h3>
<p>Wie man jetzt damit einen <span class="caps">XML</span>-Dialekt (z.B. auch <span class="caps">RSS</span>) baut, ist recht einfach, dank des <span class="caps">XML</span> Builder Gems (Das bei Rails eigentlich auch schon dabei sein sollte).<br />
Ich will hier nur ganz kurz teasern, ansonsten.. Google ist dein Freund:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt>5<tt>
</tt>6<tt>
</tt>7<tt>
</tt>8<tt>
</tt>9<tt>
</tt><strong>10</strong><tt>
</tt>11<tt>
</tt>12<tt>
</tt>13<tt>
</tt>14<tt>
</tt>15<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">require <span class="s"><span class="dl">"</span><span class="k">rubygems</span><span class="dl">"</span></span><tt>
</tt>require <span class="s"><span class="dl">"</span><span class="k">builder</span><span class="dl">"</span></span><tt>
</tt><tt>
</tt>xml = <span class="co">Builder</span>::<span class="co">XmlMarkup</span>.new( <span class="sy">:target</span> => <span class="gv">$stdout</span> , <span class="sy">:indent</span> => <span class="i">1</span> )<tt>
</tt>xml.instruct!<tt>
</tt>xml.rss <span class="r">do</span> <tt>
</tt><span class="c"># oder: xml.tag!("rss") do sinnvoll falls unser Tag nicht nur aus Kleinbuchstaben besteht</span><tt>
</tt> xml.channel <span class="r">do</span><tt>
</tt> <span class="r">for</span> item <span class="r">in</span> <span class="co">Post</span>.visible<tt>
</tt> ...<tt>
</tt> ... item.title ...<tt>
</tt><tt>
</tt> <span class="r">end</span><tt>
</tt> <span class="r">end</span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
tag:www.stefanwienert.net,2008:Post/242009-12-30T18:48:00Z2009-12-30T19:48:54ZTool fuer externe/interne Link-Analyse mit rel=nofollow<p>Fuer ein aktuelles Projekt wurde eine <b>Linkanalyse</b>, insbesondere der ausgehenden Links gewuenscht. Insbesondere die Verwendung des <span class="caps">SEO</span> Buzzwords “rel=nofollow” sollte dabei aufgezeigt werden. Was lag naeher als schnell in Ruby mit Zuhilfenahme des hpricot Gems ein kleines Skript dafuer zu bauen?</p>
<p>Das Skript gruppiert die Links in die drei Kategorien “Internal, External with nofollow, External without nofollow”. Hintergrund ist hierbei, dass das nofollow Attribut Suchmaschinen anweist, den verlinkten Seiten bei der Berechnung ihres Pagerankes diesen Link zu ignorieren. Mehr Infos in der <a href="http://de.wikipedia.org/wiki/Nofollow">Wikipedia</a>. Anmerken moechte ich noch, dass die Verwendung des Attributes umstritten ist, ich persoenlich finde es relativ ueberfluessig; Warum verlinkt man eine Seite, nur um den Suchmaschinen zu sagen, “hey, ich hab jetzt aber nicht auf die Seite verlinkt”.</p>
<p>Dank <span class="caps">XML</span> Builder ist dann auch ein ordentlicher <span class="caps">XML</span> Export kein Problem, und laesst sich so mit z.B. Firefox bequem navigieren.</p>
<p>Unter <a href="/linkcheck/link_check_form">linkcheck/link_check_form</a> findet ihr ein minimalistisches Eingabeformular. Das Ganze laesst sich natuerlich auch bequem mit <span class="caps">GET</span> ansteuern :).</p>tag:www.stefanwienert.net,2008:Post/192009-12-16T21:37:00Z2009-12-16T22:37:31ZPHP - Die beste Wahl für's Web?<p>Eines vorneweg: <span class="caps">PHP</span> war mein Einstieg in die Webprogrammierung. Die ersten Schritte haben, aufgrund der C-ähnlichen und mir damit bekannten Syntax, sogar sehr Spaß gemacht.</p>
<p>Nicht ganz ausschweigen sollte man den Fakt, dass eine Skriptsprache ganz gleich welcher Rubrik natürlich nicht das Allheilmittel jeglicher Softwareprojekte ist, weshalb ich mich hier ganz klar auf Sprachen für (private und kleinkommerzielle) Webentwicklung beschränken möchte.</p>
<h3>Story</h3>
<p>Wenn man wie ich von <span class="caps">PHP</span> kommt, ist bei Ruby und Rails vieles am Anfang ungewöhnlich, und es braucht seine Zeit, bis man sich an den Fakt, das <b>alles</b> ein Objekt ist, gewöhnen muss. Dies schafft aber auch erstklassige Möglichkeiten, Programmtext effizient und damit übersichtlich zu gestalten.</p>
<p>Im Gegensatz zu <span class="caps">PHP</span> wo ich bei trivialsten Dingen jedesmal das Rad neu erfinden muss (Ich denke nur an DateTime Handling, fortgeschrittene Stringfunktionen) hat Rails und Ruby eine sehr ausdrucksstarke Bibliothek dabei.<br />
Schön finde ich <a href="http://www.feld.com/wp/archives/2006/10/php-vs-ruby.html">diese Grafiken</a>. Hiernach wurden für <span class="caps">PHP</span>-Projekte deutlich mehr Line of Codes am Gesamtkuchen gezählt, die meiste Zunahme an Projekten überhaupt gegeben hat. Also man für eigentlich alle Projekte unter <span class="caps">PHP</span> eine Wagenladung Code mitbringen muss. <acronym title="Don't repeat yourself -- ALLES was man wiederverwenden könnte, wird ausgelagert"><span class="caps">DRY</span></acronym> <span class="caps">FTW</span>.<br />
Auch die extrem bunte Bibliothek von <span class="caps">PHP</span>, die scheinbar über die Jahre aus C-Sprachen zusammengeklaut wurde, mit total uneinheitlichen Verhalten von Funktionen: usort verändert sein Argument und gibt nichts zurück, str_replace belässt es und gibt das Ergebnis zurück.</p>
<h3>Die Syntax — Showdown</h3>
<p>Der Fakt der C-Abstammung ist für mich einer der größten Kritikpunkte, denn intuitiv ist was anderes (strstr zum Finden eines Strings…, bei Ruby: find).<br />
Wenn ich mal wieder ein etwas größeres Modul in Drupal beginn, vergesse ich so manches mal ein “;”. <br />
Das nervt und ist absolut unnötigt. Mehr als eine Anweisung ist nur für Obfascuation-Wettbewerbe geeignet. Desweiteren ist das “;” trotzdem unter Ruby <b>optional</b> nutzbar.</p>
<p>Warum diese extreme Anlehnung der Syntax an den C-Sprachen? Ist sie für betriebssystemnahe Anwendungsfälle recht angebracht, da minimal abstrakt, führt sie beim Anwendungsfallszenario “Webentwicklung” doch mehr Hürden denn Erleichterungen.</p>
<p>Warum wie ein Computer denken? Wenn ich doch wie ein Mensch denken kann? Für ein kleines µ mehr an Performance? Dafür mit einer deutlich angestiegenen Fehleranfälligkeit, teilweise unüberschaubaren Programmfluss und einer grottigen Wartbarkeit?</p>
<p>Klar ist es toll, wenn man vorher C, C++, Java oder was auch immer programmiert hat, kurz mal <span class="caps">PHP</span> sieht, und denkt “Hey, das ist ja genau das gleiche!”. Auch ich hatte diesen Aha-Effekt (Im Rückblick nichts, gegen den Aha-Effekt, den ich z.B. bei der ersten Nutzung der <acronym title="Eine Live-Shell mit Autocomplete im Kontext der Anwendung. Das heißt, man kann dort schön seine Abfragen ausprobieren, neue Nutzer anlegen usw.">script/console</acronym>, dem ersten <acronym title="Automatisches Erstellen von Formularen, DB-Tabellen und Programmlogik">scaffold</acronym> oder der Validate <—> Formularfehlermeldung hatte :D)</p>
<p><span class="caps">PHP</span> ist in meinen Augen als Websprache absolut ungeeignet.</p>
<p>Viele gute <span class="caps">PHP</span>-Frameworks wie CakePHP, Zend oder auch auch in erweiterter Bedeutung Drupal, können meiner Ansicht nach nicht über diesen Aspekt hinwegtäuschen.</p>
<p>Hier ein paar Auszüge meiner Lieblingshassobjekte:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt>4<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">htmlspecialchars <---> h<tt>
</tt>$this-> <---> Warum muss man diese <tt>
</tt>Redundanz innerhalb einer Klasse mit sich herumschleppen? <tt>
</tt>Warum "weiß" die Klasse nicht direkt über ihre Methoden?<tt>
</tt></pre></td>
</tr></table>
<p>Weitere Vorteile ergeben sich aus der kompletten Objektorientierung:</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }">str_replace("a","b","Hallo"); <---> "Hallo".gsub("a","b")<tt>
</tt>preg_match("/../",$source,$target); <---> target = /.../.match(source)<tt>
</tt></pre></td>
</tr></table>
<p>Im Endeffekt ist <span class="caps">PHP</span> sowas von laberlastig und ausdrucksschwach, dass ich z.B. bei der Entwicklung von Drupal-Modulen ohne Snippets überhaupt nicht mehr klarkommen würde. Klar liegt es vielleicht auch ein stückweit an Drupal, nichsdestotrotz bietet die aufgepfropfte Objektorientierung auch hier keine Erleichtung.</p>
<blockquote>
<p>But it’s a complex language that contains a lot of advanced idioms which will be very hard for <span class="caps">PHP</span> and Visual Basic programmers to absorb.</p>
</blockquote>
<blockquote>
<p>Sometimes, too much magic is too much magic, and it can definitely be the case that the flow of code is too direct or too clever to be understandable by regular developers. Developers were able to do the jump from imperative to object-oriented programming, but it was a hard fight.</p>
</blockquote>
<a href="http://beust.com/weblog/archives/000382.html">Quelle</a>
<p>Die vielerorts kritisierte scheinbar komfortable Konvertierung von <span class="caps">PHP</span> hat auch bei mir schon zu so manchen erstaunlichen Programmverhalten geführt.</p>
<p>Durch Rails habe ich aber auch die korrekte Benennung meiner Modelle und Datenbanktabellen gelernt. Also wenn ich eine Nutzer-Tabelle habe, dann heißt sie “users”, der Primärschlüssel “id”, ein Nutzerfremdschlüssel einer anderen Tabelle würde “user_id” heißen.<br />
Warum? Bei Rails wird man für die korrekte Benennung “belohnt”, indem einige Dinge komplett automatisch passieren, sollte man sich an die Konventionen gehalten haben. Dazu zählt: Benutzung von “partials” (Also eines View-Code-Schnipsels, dass für jedes Item eines Objekts einmal ausgeführt wird),</p>
<p>Manch einer mag anführen, dass Syntax Geschmackssache ist, und bei der Bewertung einer Sprache nur einen Teilaspekt darstellen sollte. Dem stimme absolut nicht zu. Je mehr Sonderzeichen ( “{ } ; $”) im Textfluss sind, desto schwerer lässt es sich lesen.</p>
<h3>Rails Fanboy for life?</h3>
<p>Auch bei Ruby oder Rails ist (natürlich wie immer in meinen Augen) nicht alles perfekt: neidisch blicke ich auf die Einrücksemantik von Python, spart sie mir doch die Blockschlüsselwörter. Oder das von Haus aus installierte “erb” finde ich durch “haml” erst erträglich gemacht :).</p>
<p>Auch habe ich ständig das Gefühl, dass ich erst einen Bruchteil der Sprache voll ausschöpfe. Insbesondere die funktionalen Aspekte wie procs habe ich bisher nur selten verwendet.<br />
Auch die sehr mächtigen Testmöglichkeiten durch gems wie rspec, cucumber oder silenium habe ich bisher eher akademisch benutzt.</p>
<p>In vielen Foren habe ich auch von einem fast schon spürbaren Hass auf Rails-Nutzer bemerkt; da wird von “Latte-Machiatto schlürfende” “Fanboys” geredet, die nur “oberflächliche” Anwendungen programmieren [können]. Kein Vergleich mit JavaEE, C, whatsoever. Das mag sein, dass ein Railsprojekt nicht unbedingt als System für eine Forbes 100 Firma geeignet ist, aber für sehr viele Anwendungsfälle, insbesondere bei überschaubaren Websites, mit nicht ganz 100% mainstreammäßigen also individuell Anforderungen (“Blog”, also Wordpress, Mini social Community Drupal, usw) ist es in vielerlei Hinsicht eine bessere Wahl als… <span class="caps">PHP</span>. <br />
Schön gesagt von xaviershay auf github:</p>
<blockquote>
<p>No ugly <span class="caps">PHP</span> Stylings burning your eyeballs.</p>
</blockquote>
<a href="http://github.com/xaviershay/enki">Quelle</a>
<p>Ganz ausgelassen habe ich hierbei Django/Python, dass ganz oben auf meiner Liste der zu begutachtenden Frameworks steht.</p>
<h3>Fazit?</h3>
<p>Ja ich bin subjektiv. <br />
Vielleicht liegt es an dem gut gemachten Screencast von Ryan Bates und teach-me-code? Oder der per Plugins (wirble, hirb) aufgemöbelten Liveshell irb bzw. script/generate, die mir so manchen “Ausprobier”-Lauf erspart hat (Kein Vergleich mit php -a )? Oder an dem teils humorig geschrieben Buch von O’Reilly? Oder an der Wahl der Namen? (“god” das Monitoring Tool, “sass:Syntactically awesome Stylesheets”, “<span class="caps">YAML</span>”: Yet another markup language", hpricot also wie Aprikose…)? <br />
<b>Ruby/Rails verbreitet einfach eine andere Grundstimmung</b> – Die Leute haben Spaß beim Programmieren!</p>tag:www.stefanwienert.net,2008:Post/162009-12-15T18:35:00Z2009-12-15T19:35:44ZRedmin - Full Blown Rails Bugtracking Anwendung<p>Kürzlich war ich auf der Suche nach einer guten Bugtracking Anwendung. Über den Weg gelaufen sind mir dabei:</p>
<ul>
<li><a href="http://www.mantisbt.org/">Mantis</a> in <span class="caps">PHP</span></li>
<li><a href="http://www.bugzilla.org/">Bugzilla</a> in Perl</li>
<li><a href="http://www.redmine.org/">Redmine</a> in Rails</li>
</ul>
<p>welche ich mir alle drei angeschaut habe.</p>
<p>Mein absoluter Favorit ist Redmine, welches auch eine Rails Application ist :). <br />
Vom Umfang entspricht es genau dem, was ich mir wünschte:</p>
<ul>
<li>Verwaltung mehrere Projekte, öffentlich und nicht-öffentlich</li>
<li>Feature Requests</li>
<li>Taskverwaltung/Roadmap und Berichte für abgeleistete Stunden</li>
<li>E-Mail Benachrichtigung bei Statusänderungen, neuen Bugs</li>
<li>E-Mail <span class="caps">API</span> zum Antworten</li>
</ul>
<p>Meiner Ansicht nach für die meisten kleineren bis mittelgroßen Projekten absolut ausreichend. Nicht mehr und nicht weniger.</p>
<p><b>Anmerkung</b> Da Redmine Rails ist, war hier meiner Meinung nach die Installation am leichtesten; git clone, database.yml und migrate und einen neuen Eintrag für Apache/Passenger. <br />
Ganz im Gegensatz zu Bugzilla, welche als Perl Anwendung mich erst einmal vor größere Probleme stellte :).</p>tag:www.stefanwienert.net,2008:Post/12009-10-18T08:39:00Z2009-10-11T11:39:18ZSchon wieder ein Relaunch?<p>Ich hoffe, das neue Design gefällt; dieses mal anstelle einer selbstgefrickelten Rails-Anwendung auf <a href="http://www.enkiblog.com/">Enki</a> aufsetzend.<br />
Dieses ist ein Bloggrundgerüst mit richtig geiler Adminoberfläche und… Syntaxhighlighting =).</p>
<p>Mal schaun, was die nächsten Tage noch so kommt</p><table class="CodeRay"><tr>
<td class="line_numbers" title="click to toggle" onclick="with (this.firstChild.style) { display = (display == '') ? 'none' : '' }"><pre>1<tt>
</tt>2<tt>
</tt>3<tt>
</tt></pre></td>
<td class="code"><pre ondblclick="with (this.style) { overflow = (overflow == 'auto' || overflow == '') ? 'visible' : 'auto' }"><span class="r">def</span> <span class="fu">hello_world</span><tt>
</tt> puts <span class="s"><span class="dl">"</span><span class="k">Yehaw</span><span class="dl">"</span></span><tt>
</tt><span class="r">end</span><tt>
</tt></pre></td>
</tr></table>
tag:www.stefanwienert.net,2008:Post/22009-10-11T08:40:00Z2009-10-18T10:40:56ZSEO mit Ruby (Rails)<p>Backlinks, Anzahl der Referenzen, Pagerank… all das wurde letztens für ein Projekt benötigt. Da noch einige andere Funktionen benötigt wurden, hab ich gleich eine Rails App draus gemacht.</p>
<p>Das ganze in den lib-Ordner und in der entsprechenden Datei require’n.</p>
<p>Google bietet leider keinen vernünftigen Developer-Account an, darum mache ich eine normale Browseranfrage; hierbei ist darauf zu achten, dass man nicht all zu viele Anfragen am Tag macht.<br />
Yahoo dagegen bietet eine <span class="caps">API</span> an, die uns Suchergebnisse als json zurückliefert.<br />
Die beiden Klassen google und yahoo lassen sich natürlich noch erweitern: momentan geben sie nur die Anzahl der Suchergebnisse und das jeweils erste zurück. Es ist noch nicht perfekt, aber für meine Zwecke erstmal ausreichend. Bitte beachtet auch die Quellenangaben.</p>
<p><a href="http://stefanwienert.net/~zealot128/dokuwiki/doku.php?id=tutorial:ruby_rails">Quelltext ist jetzt im Wiki</a></p>tag:www.stefanwienert.net,2008:Post/52009-08-18T08:47:00Z2009-10-18T10:47:18Z3 Links zum Thema Rails<p>Einen interessanten Artikel aus dem t3n-Magazin zum Thema Rapid-Prototyping gibt es hier:<br />
<a href="http://t3n.de/magazin/schnell-kommt-ohne-neue-buchstaben-erfinden-222480/">t3n-rapidprototyping</a></p>
<p>Weiterhin, für alle Rails-Jünger natürlich unverzichtbar sind die Screencasts von Ryan Bates, die einfach nur Spaß machen, und meiner Meinung nach zu den besten (frei erhältlichen) Screencasts im Netz gehören!<br />
<a href="http://railscasts.com/episodes/">railscasts</a></p>
<p>Als Umsteiger von <span class="caps">PHP</span> fand ich diese Seite auch noch recht interessant, in der äquivalente Rails/Ruby-Konstrukte gängige <span class="caps">PHP</span>-Funktionen abgebildet werden :)<br />
<a href="http://railsforphp.com/reference/strings/htmlentities">rails4php</a></p>