<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
	xmlns:media="http://search.yahoo.com/mrss/"
>

<channel>
	<title>Catholicism Computes</title>
	<atom:link href="http://blog.purepistos.net/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.purepistos.net</link>
	<description>life, music, religion and computers</description>
	<lastBuildDate>Mon, 29 Mar 2010 02:36:05 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
		<!-- podcast_generator="podPress/8.8" - maintenance_release="8.8.4" -->
		<copyright>2006-2009 </copyright>
		<managingEditor>catholicismcomputes.pistos@purepistos.net (Pistos)</managingEditor>
		<webMaster>catholicismcomputes.pistos@purepistos.net (Pistos)</webMaster>
		<category>posts</category>
		<ttl>1440</ttl>
		<itunes:keywords></itunes:keywords>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:author>Pistos</itunes:author>
		<itunes:category text="Society &amp; Culture"/>
		<itunes:owner>
			<itunes:name>Pistos</itunes:name>
			<itunes:email>catholicismcomputes.pistos@purepistos.net</itunes:email>
		</itunes:owner>
		<itunes:block>No</itunes:block>
		<itunes:explicit>no</itunes:explicit>
		<itunes:image href="http://blog.purepistos.net/wp-content/themes/catholicism-computes/images/catholicism-computes-image.jpg" />
		<image>
			<url>http://blog.purepistos.net/wp-content/themes/catholicism-computes/images/catholicism-computes-image.jpg</url>
			<title>Catholicism Computes</title>
			<link>http://blog.purepistos.net</link>
			<width>144</width>
			<height>144</height>
		</image>
		<item>
		<title>Debussy &#8211; Clair de Lune</title>
		<link>http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/</link>
		<comments>http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 02:36:05 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[clair]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[debussy]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[lune]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=589</guid>
		<description><![CDATA[The third movement of Claude Debussy&#8217;s Suite Bergamasque, popularly known as Clair de Lune.

Read more about my piano recording series here.




Related posts:Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement
Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement
Chopin &#8211; Prelude Op. 28, No. 4 in E minor



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The third movement of Claude Debussy&#8217;s Suite Bergamasque, popularly known as Clair de Lune.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2010%2F03%2F28%2Fdebussy-clair-de-lune%2F&amp;linkname=Debussy%20%26%238211%3B%20Clair%20de%20Lune"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/debussy/pistos--debussy-clair-de-lune.mp3" length="10525427" type="audio/mpeg"/>
<itunes:duration>4:23</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</title>
		<link>http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/</link>
		<comments>http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 01:20:02 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[military]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[polonaise]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=580</guid>
		<description><![CDATA[The Military Polonaise by Fr&#233;d&#233;ric Chopin.  This sort of piece is at the edge of my technical ability; I hope it does not show too much.   

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Chopin &#8211; Mazurka in Ab Major, Op. 24, No. [...]


Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The Military Polonaise by Fr&eacute;d&eacute;ric Chopin.  This sort of piece is at the edge of my technical ability; I hope it does not show too much.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2010%2F02%2F22%2Fchopin-polonaise-op-40-no-1-in-a-major%2F&amp;linkname=Chopin%20%26%238211%3B%20Polonaise%20Op.%2040%2C%20No.%201%20in%20A%20Major"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--chopin-polonaise-op-40-no-1.mp3" length="13008098" type="audio/mpeg"/>
<itunes:duration>5:25</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Thankful Eyes &#8211; make text on the web readable</title>
		<link>http://blog.purepistos.net/index.php/2010/02/03/thankful-eyes-make-text-on-the-web-readable/</link>
		<comments>http://blog.purepistos.net/index.php/2010/02/03/thankful-eyes-make-text-on-the-web-readable/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 19:07:59 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=572</guid>
		<description><![CDATA[Thankful Eyes is a bookmarklet which automatically calculates and applies a large enough font size to body text for optimum readability.  It&#8217;s a little project I worked on recently, and I think it is ready for general beta testing and real-world usage.  It works in Opera and Firefox (untested in IE).  Known [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Thankful Eyes is a bookmarklet which automatically calculates and applies a large enough font size to body text for optimum readability.  It&#8217;s a little project I worked on recently, and I think it is ready for general beta testing and real-world usage.  It works in Opera and Firefox (untested in IE).  Known not to work under Safari or Chrome [yet].</p>

<ul>
<li><a href="http://purepistos.net/thankful-eyes">Homepage</a> (grab the bookmarklet from there)</li>
<li><a href="http://github.com/Pistos/Thankful-Eyes">Source code on github</a></li>
</ul>

<p><a href="http://www.google.com/search?q=%2212+words+per+line%22">It is said</a> that, for optimum readability, text line length should be around 12 words per line. This allows the eye to easily track from the end of one line to the beginning of the next.</p>

<p>Using Thankful Eyes is better than simply maintaining a minimum font size with your browser settings because doing that increases the size of many elements which usually do not require magnification, such as sidebar text, menu items, small labels, and so on. Thankful Eyes aims to adjust only body text.  It&#8217;s also better than using browser zoom, because browser zoom also magnifies and distorts images.</p>

<p>Leave feedback here, or come <a href="http://webchat.freenode.net/?channels=mathetes">visit me in IRC</a> on the FreeNode network.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2010%2F02%2F03%2Fthankful-eyes-make-text-on-the-web-readable%2F&amp;linkname=Thankful%20Eyes%20%26%238211%3B%20make%20text%20on%20the%20web%20readable"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2010/02/03/thankful-eyes-make-text-on-the-web-readable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</title>
		<link>http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/</link>
		<comments>http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/#comments</comments>
		<pubDate>Tue, 12 Jan 2010 05:12:54 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[Eb]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[major]]></category>
		<category><![CDATA[nocturne]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=560</guid>
		<description><![CDATA[The famous Nocturne in Eb Major by Chopin.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 72, No. 1 in E minor
Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3
Chopin &#8211; Polonaise Op. 40, No. 1 in A Major



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The famous Nocturne in Eb Major by Chopin.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2010%2F01%2F12%2Fchopin-nocturne-op-9-no-2-in-eb-major%2F&amp;linkname=Chopin%20%26%238211%3B%20Nocturne%20Op.%209%2C%20No.%202%20in%20Eb%20Major"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--chopin-nocturne-op-9-no-2.mp3" length="8568325" type="audio/mpeg"/>
<itunes:duration>3:34</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</title>
		<link>http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/</link>
		<comments>http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/#comments</comments>
		<pubDate>Tue, 22 Dec 2009 04:40:08 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[28]]></category>
		<category><![CDATA[4]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[e]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[minor]]></category>
		<category><![CDATA[opus]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[prelude]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=551</guid>
		<description><![CDATA[Another short Prelude by le maître.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 72, No. 1 in E minor
Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Another short Prelude by <i>le maître</i>.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F12%2F21%2Fchopin-prelude-op-28-no-4-in-e-minor%2F&amp;linkname=Chopin%20%26%238211%3B%20Prelude%20Op.%2028%2C%20No.%204%20in%20E%20minor"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--prelude-op-28-no-4.mp3" length="3559072" type="audio/mpeg"/>
<itunes:duration>1:29</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</title>
		<link>http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/</link>
		<comments>http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/#comments</comments>
		<pubDate>Sat, 05 Dec 2009 08:50:34 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[mazurka]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=543</guid>
		<description><![CDATA[A light mazurka that I found when leafing through my Chopin score collection.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Chopin &#8211; Polonaise Op. 40, No. 1 in A Major
Chopin &#8211; Nocturne Op. 72, No. 1 in E minor



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>A light mazurka that I found when leafing through my Chopin score collection.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F12%2F05%2Fchopin-mazurka-in-ab-major-op-24-no-3%2F&amp;linkname=Chopin%20%26%238211%3B%20Mazurka%20in%20Ab%20Major%2C%20Op.%2024%2C%20No.%203"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--chopin-mazurka-op-24-no-3.mp3" length="4335227" type="audio/mpeg"/>
<itunes:duration>2:15</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</title>
		<link>http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/</link>
		<comments>http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 02:58:29 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[e]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[melancholy]]></category>
		<category><![CDATA[nocturne]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>
		<category><![CDATA[sad]]></category>
		<category><![CDATA[sombre]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=531</guid>
		<description><![CDATA[An emotional Nocturne by Chopin.  It starts out melancholy, but the greyness passes away as the piece journeys to its E major resolution.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Chopin &#8211; Prelude Op. 28, No. 4 in E minor
Chopin &#8211; Polonaise Op. 40, No. [...]


Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>An emotional Nocturne by Chopin.  It starts out melancholy, but the greyness passes away as the piece journeys to its E major resolution.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F10%2F16%2Fchopin-nocturne-op-72-no-1-in-e-minor%2F&amp;linkname=Chopin%20%26%238211%3B%20Nocturne%20Op.%2072%2C%20No.%201%20in%20E%20minor"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--chopin-nocturne-op-72-no-1.mp3" length="3348422" type="audio/mpeg"/>
<itunes:duration>3:29</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</title>
		<link>http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/</link>
		<comments>http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/#comments</comments>
		<pubDate>Sun, 20 Sep 2009 17:24:13 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[beethoven]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[moonlight]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>
		<category><![CDATA[sonata]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=500</guid>
		<description><![CDATA[The second movement of Beethoven&#8217;s famous Moonlight Sonata (No. 14).

Read more about my piano recording series here.




Related posts:Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement
Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Debussy &#8211; Clair de Lune



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/' rel='bookmark' title='Permanent Link: Debussy &#8211; Clair de Lune'>Debussy &#8211; Clair de Lune</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The second movement of Beethoven&#8217;s famous Moonlight Sonata (No. 14).</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F09%2F20%2Fbeethoven-sonata-op-27-no-2-moonlight-2nd-movement%2F&amp;linkname=Beethoven%20%26%238211%3B%20Sonata%20Op.%2027%2C%20No.%202%20%28Moonlight%29%2C%202nd%20movement"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/' rel='bookmark' title='Permanent Link: Debussy &#8211; Clair de Lune'>Debussy &#8211; Clair de Lune</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/beethoven/pistos--beethoven-sonata-op-27-no-2-2nd-mvmt.mp3" length="2438142" type="audio/mpeg"/>
<itunes:duration>2:32</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</title>
		<link>http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/</link>
		<comments>http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/#comments</comments>
		<pubDate>Fri, 18 Sep 2009 02:03:28 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[beethoven]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[moonlight]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>
		<category><![CDATA[sonata]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=494</guid>
		<description><![CDATA[The first movement of Beethoven&#8217;s famous Moonlight Sonata No. 14 in C# minor.

Read more about my piano recording series here.




Related posts:Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement
Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Debussy &#8211; Clair de Lune



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/' rel='bookmark' title='Permanent Link: Debussy &#8211; Clair de Lune'>Debussy &#8211; Clair de Lune</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The first movement of Beethoven&#8217;s famous Moonlight Sonata No. 14 in C# minor.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F09%2F17%2Fbeethoven-sonata-op-27-no-2-moonlight-1st-movement%2F&amp;linkname=Beethoven%20%26%238211%3B%20Sonata%20Op.%2027%2C%20No.%202%20%28Moonlight%29%2C%201st%20movement"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/03/28/debussy-clair-de-lune/' rel='bookmark' title='Permanent Link: Debussy &#8211; Clair de Lune'>Debussy &#8211; Clair de Lune</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/beethoven/pistos--beethoven-sonata-op-27-no-2-1st-mvmt.mp3" length="5057498" type="audio/mpeg"/>
<itunes:duration>5:16</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Diakonos &#8211; version 0.8.12</title>
		<link>http://blog.purepistos.net/index.php/2009/08/01/diakonos-version-0812/</link>
		<comments>http://blog.purepistos.net/index.php/2009/08/01/diakonos-version-0812/#comments</comments>
		<pubDate>Sat, 01 Aug 2009 19:12:48 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[announcement]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=477</guid>
		<description><![CDATA[Version 0.8.12 of Diakonos is now available.

Keying and the input line

The keying system of Diakonos has been refactored.  What this means to the end user is the input line now supports the full range of keys.  For example, keys like the Home and End keys actually produce multiple characters of input each, and [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.12 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.</p>

<h4>Keying and the input line</h4>

<p>The keying system of Diakonos has been refactored.  What this means to the end user is the input line now supports the full range of keys.  For example, keys like the Home and End keys actually produce multiple characters of input each, and so would not function properly in older versions.  They are now are properly supported.  As part of this new implementation, the notion of keying modes has been introduced.  For now, there are only two hard-coded modes: &#8220;edit&#8221; and &#8220;input&#8221;.  There is now an <code>mkey</code> configuration directive, used to bind a function to a key chord or sequence under a specific mode.  The old directive, <code>key</code> is equivalent to <code>mkey edit</code>, and so acts as a shorthand.  <span id="more-477"></span></p>

<p>Another nice enhancement to input is the fact that the input line can now scroll left and right, to allow proper editing of long inputs (inputs wider than the screen or terminal).</p>

<h4>zsh and bash completion</h4>

<p>This version includes in the tarballs files that can be used to provide tab completion for Diakonos under bash and zsh.  Of course, all shells already provide tab completion for files and directories, but with the provided files, you can also have completion of session names for use with <code>diakonos -s &lt;session&gt;</code>.</p>

<h4>Selection and Find</h4>

<p>A new <code>select_wrapping_block</code> function has been added, with a default keychord of Alt-space.  This function will select all lines at the current level of indentation (or deeper).  That is, you can select the current code block with it.  You can press Alt-space additional times to quickly and easily select increasingly shallower parent blocks.</p>

<p>The find functionality of Diakonos has been enhanced: if you perform a search with text selected, the search is restricted to the selected text.  Put these two new features together, and you have a way to restrict searches to code blocks &#8212; something I find quite cool and useful.  Haven&#8217;t you ever wanted to know &#8220;where else do I reference this variable within this method?&#8221; or asked similar questions?  Well now you can find out things like this very easily.</p>

<h4>Cursor stack</h4>

<p>The cursor stack was broken in the last release, but it has been repaired and also enhanced.  The cursor stack is now cross-buffer, instead of buffer-specific.  This lets you return to logical work areas no matter which buffers they are in.  (For those of you that don&#8217;t know, the cursor stack is essentially the equivalent of your web browser&#8217;s Back and Forward functionality, except within your editor.)</p>

<h4>git integration</h4>

<p>Diakonos git integration got a big boost recently, by way of a really cool git tool called <a href="http://jonas.nitro.dk/tig/">tig</a>.  Of course, tig is neither required for Diakonos operation, nor bundled with Diakonos.  However, if you install it, and also install <a href="http://github.com/Pistos/dk-git/tree/master">the Diakonos git extension</a>, then you get one-key access (F9) to a slick curses interface to git.  If you are a git user, I certainly recommend you take tig for a whirl.  With dk-git and tig, we Diakonos users get something comparable to emacs&#8217; <a href="http://zagadka.vm.bytemark.co.uk/magit/magit.html">magit</a>.</p>

<h4>Changelog</h4>

<p>The full set of changes is listed in greater detail in the <a href="http://github.com/Pistos/diakonos/tree/v0.8.12/CHANGELOG">changelog</a>:</p>

<ul>
<li>Refactored keying system.</li>
<li>Introduced keying modes.</li>
<li>Ruby version now enforced, both at installation and run time.</li>
<li>Input line can now scroll if input is longer than screen width.</li>
<li>Added support for session completion in zsh and bash.</li>
<li>Added select_line.</li>
<li>Added select_wrapping_block (default key: Alt-space).</li>
<li>Searching is now restricted to the selected text, if any.</li>
<li>Added view.non_search_area.format.</li>
<li>Fixed cursor stack.</li>
<li>Cursor stack is now global (cross-buffer).</li>
<li>Simplified switch_to_next_buffer and switch_to_prev_buffer; no more history.</li>
<li>Added chdir function.</li>
<li>Various refactorings.</li>
<li>Various bug fixes.</li>
</ul>

<p>As usual, report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://webchat.freenode.net/?channels=mathetes">visit me in IRC</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F08%2F01%2Fdiakonos-version-0812%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.12"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/08/01/diakonos-version-0812/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Diakonos &#8211; version 0.8.11</title>
		<link>http://blog.purepistos.net/index.php/2009/07/07/diakonos-version-0811/</link>
		<comments>http://blog.purepistos.net/index.php/2009/07/07/diakonos-version-0811/#comments</comments>
		<pubDate>Tue, 07 Jul 2009 10:18:31 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[extension]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=450</guid>
		<description><![CDATA[Version 0.8.11 of Diakonos is now available.

This release brings a handful of minor feature enhancements and fixes, but the most important addition is the new extension system. 

Diakonos Extensions

Diakonos has been scriptable for many versions now, but with this release I have baked in an official system and structure for extensions.  Diakonos dances to [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.11 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.</p>

<p>This release brings a handful of minor feature enhancements and fixes, but the most important addition is the new extension system. <span id="more-450"></span></p>

<h3>Diakonos Extensions</h3>

<p>Diakonos has been scriptable for many versions now, but with this release I have baked in an official system and structure for extensions.  Diakonos dances to the same tune as Ruby, insofar as it exposes pretty much the entire core to any enterprising developer who wants to add new features.  Later on, I&#8217;ll describe some of the ways a programmer might extend Diakonos, but first, let&#8217;s take a look at the Hello World extension that comes with the Diakonos tarball.</p>

<h4>The Anatomy of an Extension</h4>

<p>Every extension must have an <code>info.yaml</code> file.  This <a href="http://en.wikipedia.org/wiki/YAML">YAML</a> file contains lots of information about the extension.  Here are the contents of the <code>info.yaml</code> file of the Hello World extension:</p>


<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;">name: Hello World
description: An example of a Diakonos extension
author:
    name: Pistos
    email: somebody@example.com
    uri: http://blog.purepistos.net
version: 1.0.0
uris:
    homepage: http://github.com/Pistos/diakonos/tree/master/extensions/dk-hello-world
    repository: git://github.com/Pistos/diakonos.git
licence: MIT
requirements:
    diakonos:
        minimum: 0.8.11
        tested:
            - 0.8.11
    gems:
        # - gemname:
            # minimum: 1.0.0
            # tested:
                # - 1.0.0
                # - 1.1.0
notes: &gt;
    This extension adds a hello_world function to Diakonos.
&nbsp;
    Pressing Shift-F11 will activate the function.</pre></div></div>


<p>I think the file contents and format are self-explanatory.  The only thing to keep in mind is that the <code>requirements</code> key is required.  All other items are optional.  The fields are all fully described in Diakonos&#8217; built-in help.</p>

<p>Besides the <code>info.yaml</code> file, an extension can have one or more <code>.conf</code> and <code>.rb</code> files.  The <code>.conf</code> files are of the same format as normal Diakonos configuration files.  The Ruby (<code>.rb</code>) files are where all the code of the extension is placed.</p>

<p>Here is the code of the Hello World extension:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Diakonos
  <span style="color:#9966CC; font-weight:bold;">module</span> Functions
    <span style="color:#9966CC; font-weight:bold;">def</span> hello_world
      <span style="color:#0066ff; font-weight:bold;">@current_buffer</span>.<span style="color:#9900CC;">paste</span> <span style="color:#996600;">&quot;Hello, world!&quot;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>In it, a new function, <code>hello_world</code>, is defined.  Obviously, it pastes &#8220;Hello, world!&#8221; into the current buffer (at the current cursor position).</p>

<p>The Hello World conf file has just this line:</p>

<pre>
key f23   hello_world
</pre>

<p>So, once the Hello World extension is loaded, you can press Shift-F11, and you&#8217;ll receive the well-known greeting.</p>

<h4>Managing Extensions</h4>

<p>Extensions are simply self-contained directories of files, and so can be packaged into tarballs, made into git repositories, or whatever strikes your fancy.</p>

<p>To install an extension, just copy or unpack (or even symlink) its directory under ~/.diakonos/extensions/.  For example, ~/.diakonos/extensions/dk-hello-world/.</p>

<p>To activate an extension, use the <code>load_extension</code> directive in your Diakonos configuration.  For example:</p>

<pre>
load_extension dk-hello-world
</pre>

<p>You can see what extensions are loaded and active with the new About page, accessible with default hotkey F11.  Any extensions that failed to load will also be listed.</p>

<h4>What Extensions Can Do</h4>

<p>An extension might do any number of things, like:</p>

<ul>
<li>provide a new language definition</li>
<li>set up an alternative key mapping</li>
<li>provide an alternative shared or default colour scheme</li>
<li>share a user&#8217;s personal configuration settings</li>
<li>add new functions to Diakonos, and map them to keys</li>
<li>provide new status line variables</li>
<li>install code to run on Diakonos hooks</li>
</ul>

<p>The range of possibilities is very broad.  I have begun filling out source code documentation for Diakonos.  I hope to add more and more documentation with each release.  The current docs can be accessed at <a href="http://purepistos.net/diakonos/rdoc/">http://purepistos.net/diakonos/rdoc/</a>.  As of this writing, it&#8217;s quite incomplete, but at least the classes and methods are enumerated.  Since this documentation is sparse, don&#8217;t be afraid to dive right into <a href="http://github.com/Pistos/diakonos/tree/master">the source code</a>.  Although I am continually refactoring, and some [very] old code is still hanging around, I think most of the codebase is readable and understandable.  Also, of course, you can always come and ask questions in <a href="http://webchat.freenode.net/?channels=mathetes">our IRC channel</a> if you need help with writing extensions, or using Diakonos in general.</p>

<h4>Example Extensions</h4>

<p>A few extensions have already been made to help exemplify the new extension system.  Check out their source to learn more about extending Diakonos.</p>

<ul>
<li><a href="http://github.com/Pistos/diakonos/tree/branch-0.8.11/extensions/dk-hello-world">Hello World</a> &#8211; A minimal example extension</li>
<li><a href="http://github.com/Pistos/dk-git/tree/master">git</a> &#8211; A git extension</li>
<li><a href="http://github.com/Pistos/dk-selector/tree/master">Selector</a> &#8211; An extension for CSS/XPath selecting on the current HTML/XML buffer</li>
<li><a href="http://github.com/dominikh/dk-comment-toggle/tree/master">Comment Toggle</a> &#8211; Smart (un)commenting for Diakonos</li>
</ul>

<h3>Release Changelog</h3>

<p>Here is the detailed <a href="http://github.com/Pistos/diakonos/tree/v0.8.11/CHANGELOG">changelog</a> for this release:</p>

<ul>
<li>Added join_lines_upward (Alt-Shift-J).</li>
<li>Added one-key selection in buffer list.</li>
<li>Added support for single line indentation.</li>
<li>Added extension system.</li>
<li>Added surround_selection and related functions.</li>
<li>Added &#8220;about&#8221; page.</li>
<li>Various bug fixes and refactorings.</li>
</ul>

<p>Report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://webchat.freenode.net/?channels=mathetes">visit me in IRC</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F07%2F07%2Fdiakonos-version-0811%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.11"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/07/07/diakonos-version-0811/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Diakonos &#8211; version 0.8.10</title>
		<link>http://blog.purepistos.net/index.php/2009/06/23/diakonos-version-0810/</link>
		<comments>http://blog.purepistos.net/index.php/2009/06/23/diakonos-version-0810/#comments</comments>
		<pubDate>Wed, 24 Jun 2009 04:09:13 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=434</guid>
		<description><![CDATA[Version 0.8.10 of Diakonos is now available.

With this release, I&#8217;d like to welcome Dominik Honnef (dominikh) to the Diakonos development team.  He has already made several contributions, including some fixes which were cherry-picked from the master development branch and included in this version.  His other contributions to date will be seen in the [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.10 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.</p>

<p>With this release, I&#8217;d like to welcome Dominik Honnef (<a href="http://github.com/dominikh/">dominikh</a>) to the Diakonos development team.  He has already made several contributions, including some fixes which were cherry-picked from the master development branch and included in this version.  His other contributions to date will be seen in the next version (0.8.11), and I think we can expect more from him in future versions.</p>

<p>Starting with this version, Ruby 1.8 support is officially dropped.  Diakonos will now only run on Ruby 1.9.  There&#8217;s no need to rush the upgrade on your systems; it is quite possible to have both 1.8 and 1.9 installed on the same system.  Search the web for how to do this.</p>

<p><span id="more-434"></span> go_to_char (Alt-N) and go_to_char_previous (Alt-P) have been added.  These let you move the cursor directly to a specific nearby character.</p>

<p>The shell command has been adjusted a little, so that the results buffer is no longer cluttered with the command that was run.</p>

<p>The way you activate Klipper synchronization has been centralized and simplified.  You now simply set &#8220;clipboard.external klipper&#8221;, instead of setting each clipboard-related key mapping.  Along with this change, <a href="http://sourceforge.net/projects/xclip">xclip</a> support was added.  This will let non-KDE users synchronize their X clipboard with Diakonos.</p>

<p>Sessions have been improved a bit: Cursor position is now saved, and Diakonos also remembers which was the current buffer when restoring a session.</p>

<p>Basic pair highlighting and jumping was added.  Matching brackets are now highlighted, and you can press Alt-{ to jump to a match.</p>

<p>Dynamic prefix expansion was added.  With this feature, you can complete long words &#8212; good for those of us who don&#8217;t like to type a lot.  Type the beginning of a long variable name, or such, then press Alt-E.  Diakonos will complete the word using a word found in the open buffers (the most frequently used one).  Press Alt-E more times to cycle through all the matches.  Here is a screencast which shows this feature in action:</p>

<p><center><OBJECT CLASSID="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" WIDTH="451" HEIGHT="166" CODEBASE="http://active.macromedia.com/flash5/cabs/swflash.cab#version=5,0,0,0">
<PARAM NAME=movie VALUE="prefix-expansion.swf">
<PARAM NAME=play VALUE=true>
<PARAM NAME=loop VALUE=false>
<PARAM NAME=quality VALUE=low>
<EMBED SRC="/wp-content/uploads/diakonos/prefix-expansion.swf" WIDTH=451 HEIGHT=166 quality=low loop=false TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
</EMBED>
</OBJECT>
</center></p>

<p>Here is the full <a href="http://github.com/Pistos/diakonos/tree/v0.8.10/CHANGELOG">changelog</a> for this version:</p>

<ul>
<li>Ruby version 1.9+ now required.  (Ruby 1.8 support dropped)</li>
<li>Added go_to_char (Alt-N).</li>
<li>Added go_to_char_previous (Alt-P).</li>
<li>shell command now shows executed command on interaction line.</li>
<li>shell command is now interruptible.</li>
<li>Klipper synchronization now a single setting (clipboard.external klipper).</li>
<li>Added xclip support.</li>
<li>Cursor and viewport positions now saved in and restored from sessions.</li>
<li>Current buffer number now saved in sessions.</li>
<li>Fixed context line.</li>
<li>Textual indication of no shell results now given.</li>
<li>Added basic pair (bracket) highlighting.</li>
<li>Added go_to_pair_match (Alt-Shift-[).</li>
<li>Fixed chmodding in installer.</li>
<li>Undo and redo now actually compare file contents to set &#8220;modified&#8221; flag.</li>
<li>Added support for a special &#8216;all&#8217; language, whose formats apply no matter the current language.</li>
<li>Added dynamic prefix expansion (Alt-E).</li>
</ul>

<p>Report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://webchat.freenode.net/?channels=mathetes">visit me in IRC</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F06%2F23%2Fdiakonos-version-0810%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.10"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/06/23/diakonos-version-0810/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Diakonos &#8211; version 0.8.9</title>
		<link>http://blog.purepistos.net/index.php/2009/06/14/diakonos-version-089/</link>
		<comments>http://blog.purepistos.net/index.php/2009/06/14/diakonos-version-089/#comments</comments>
		<pubDate>Sun, 14 Jun 2009 19:37:04 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=426</guid>
		<description><![CDATA[Version 0.8.9 of Diakonos is now available.

This release is primarily an internal refactor release.  The only changes visible to the user are bug fixes.  These include improvements to the installer, and vastly improved handling of X windows pasting.  No more brutally slow terminal pasting!

The changes are listed in greater detail in the [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.9 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.</p>

<p>This release is primarily an internal refactor release.  The only changes visible to the user are bug fixes.  These include improvements to the installer, and vastly improved handling of X windows pasting.  No more brutally slow terminal pasting!</p>

<p>The changes are listed in greater detail in the <a href="http://github.com/Pistos/diakonos/tree/v0.8.9/CHANGELOG">changelog</a>:</p>

<ul>
<li>Put interaction timer only on first stale session prompt, not any after that.</li>
<li>Changed all function names from camelCase to snake_case.</li>
<li>Added &#8211;help-dir switch to installer.</li>
<li>Fixed some issues with installer.</li>
<li>Changed delete_to_and_from to always assume given character is the left side character when matching pairs.</li>
<li>Fixed a line number display bug.</li>
<li>X windows pasting handled much better now.</li>
<li>Numerous internal refactorings and reorganizations.</li>
<li>Accepted patches from Decklin Foster.</li>
</ul>

<p>Report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes">visit me in IRC</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F06%2F14%2Fdiakonos-version-089%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.9"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/06/14/diakonos-version-089/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Beethoven &#8211; F&#252;r Elise</title>
		<link>http://blog.purepistos.net/index.php/2009/06/13/beethoven-fur-elise/</link>
		<comments>http://blog.purepistos.net/index.php/2009/06/13/beethoven-fur-elise/#comments</comments>
		<pubDate>Sat, 13 Jun 2009 14:33:03 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[beethoven]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[elise]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[fur]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=419</guid>
		<description><![CDATA[The very popular Bagatelle in A minor by Beethoven, commonly known as F&#252;r Elise.

Read more about my piano recording series here.




Related posts:Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement
Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement
Chopin &#8211; Prelude Op. 28, No. 4 in E minor



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>The very popular Bagatelle in A minor by Beethoven, commonly known as <i>F&uuml;r Elise</i>.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F06%2F13%2Fbeethoven-fur-elise%2F&amp;linkname=Beethoven%20%26%238211%3B%20F%26uuml%3Br%20Elise"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/09/17/beethoven-sonata-op-27-no-2-moonlight-1st-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 1st movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/09/20/beethoven-sonata-op-27-no-2-moonlight-2nd-movement/' rel='bookmark' title='Permanent Link: Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement'>Beethoven &#8211; Sonata Op. 27, No. 2 (Moonlight), 2nd movement</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/06/13/beethoven-fur-elise/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/beethoven/pistos--beethoven-fur-elise.mp3" length="2538266" type="audio/mpeg"/>
<itunes:duration>2:39</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Ramaze vs. Rails: Battle of the default templating engines</title>
		<link>http://blog.purepistos.net/index.php/2009/06/02/ramaze-vs-rails-battle-of-the-default-templating-engines/</link>
		<comments>http://blog.purepistos.net/index.php/2009/06/02/ramaze-vs-rails-battle-of-the-default-templating-engines/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 16:14:53 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[bench]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[default]]></category>
		<category><![CDATA[erb]]></category>
		<category><![CDATA[etanni]]></category>
		<category><![CDATA[faster]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[speed]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[templating]]></category>
		<category><![CDATA[versus]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=398</guid>
		<description><![CDATA[Someone asked recently on the Ramaze mailing list:


  Is Etanni a performance improvement over ERB?  I&#8217;m just converting a site over to Ramaze and I&#8217;m wondering if it&#8217;d be worthwhile to convert my ERB tags to Etanni tags?   


manveru promptly replied:


  ERB is a lot larger, and does a lot [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Someone asked recently on the Ramaze mailing list:</p>

<blockquote>
  <p>Is Etanni a performance improvement over ERB?  I&#8217;m just converting a site over to Ramaze and I&#8217;m wondering if it&#8217;d be worthwhile to convert my ERB tags to Etanni tags?  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</blockquote>

<p>manveru promptly replied:</p>

<blockquote>
  <p>ERB is a lot larger, and does a lot more, but usually you don&#8217;t use that functionality. Etanni consists of a single regular expression substitution and should be faster than just about any other templating engine around, the <a href="http://github.com/manveru/innate/blob/master/lib/innate/view/etanni.rb">whole core source of Etanni</a> is around 4 lines.</p>
  
  <p>So yes, i suggest you use Etanni instead of ERB <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
</blockquote>

<p>He also quickly wrote up <a href="http://pastr.it/16178">some benchmarking code</a> to substantiate his claims, and then enlisted me to solidify matters.  I used his code as a base, and ran the same engine test code through <a href="http://github.com/Pistos/better-benchmark/tree/master">better-benchmark</a>.  I put <a href="http://gist.github.com/122070">the benchmarking code</a> up as a gist.  The full results are embedded as a comment at the end of the gist.  Here is a summary:</p>

<table class="table">
<tr><th>Template type</th><th>Etanni faster<br/>than ERb by</th></tr>
<tr><td>Just HTML (no templating)</td><td>38.3%</td></tr>
<tr><td>In-template loop with expression interpolation</td><td>20.7%</td></tr>
<tr><td>Ruby expression evaluation</td><td>43.9%</td></tr>
</table>

<p>Based on the results of this little test we might conclude: If rendering speed is a concern, but you also want to just stick with your framework&#8217;s default engine to minimize gem dependencies, go with <a href="http://ramaze.net">Ramaze</a>.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F06%2F02%2Framaze-vs-rails-battle-of-the-default-templating-engines%2F&amp;linkname=Ramaze%20vs.%20Rails%3A%20Battle%20of%20the%20default%20templating%20engines"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/06/02/ramaze-vs-rails-battle-of-the-default-templating-engines/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Chaminade &#8211; Scarf Dance, Op. 37, No. 3</title>
		<link>http://blog.purepistos.net/index.php/2009/05/29/chaminade-scarf-dance-op-37-no-3/</link>
		<comments>http://blog.purepistos.net/index.php/2009/05/29/chaminade-scarf-dance-op-37-no-3/#comments</comments>
		<pubDate>Sat, 30 May 2009 02:37:18 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[ballet]]></category>
		<category><![CDATA[chaminade]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[dance]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>
		<category><![CDATA[scarf]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=390</guid>
		<description><![CDATA[This piece, also known as Der Sch&#228;rpentanz or Pas des &#233;charpes, is by French pianist and composer C&#233;cile Chaminade.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 72, No. 1 in E minor
Chopin &#8211; Polonaise Op. 40, No. 1 in A Major
Chopin &#8211; Prelude Op. 28, No. 4 in E minor



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>This piece, also known as <i>Der Sch&auml;rpentanz</i> or <i>Pas des &eacute;charpes</i>, is by French pianist and composer C&eacute;cile Chaminade.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F05%2F29%2Fchaminade-scarf-dance-op-37-no-3%2F&amp;linkname=Chaminade%20%26%238211%3B%20Scarf%20Dance%2C%20Op.%2037%2C%20No.%203"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/05/29/chaminade-scarf-dance-op-37-no-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chaminade/pistos--chaminade-scarf-dance-op-37-no-3.mp3" length="1743307" type="audio/mpeg"/>
<itunes:duration>1:49</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>8 reasons why I prefer FriendFeed over Twitter</title>
		<link>http://blog.purepistos.net/index.php/2009/05/19/8-reasons-why-i-prefer-friendfeed-over-twitter/</link>
		<comments>http://blog.purepistos.net/index.php/2009/05/19/8-reasons-why-i-prefer-friendfeed-over-twitter/#comments</comments>
		<pubDate>Tue, 19 May 2009 15:45:33 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[friendfeed]]></category>
		<category><![CDATA[networking]]></category>
		<category><![CDATA[replies]]></category>
		<category><![CDATA[reply]]></category>
		<category><![CDATA[social]]></category>
		<category><![CDATA[twitter]]></category>
		<category><![CDATA[versus]]></category>
		<category><![CDATA[vs]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=338</guid>
		<description><![CDATA[On account of the recent Twitter reply system fiasco (see Twitter blog entries 1, 2, 3, 4 and related backlash spewed across the Internet), 
I recently joined FriendFeed on recommendation by Jaykul.  It didn&#8217;t take long for me to be really impressed with this service, and for Twitter to look pretty rinky-dink in comparison.

If [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>On account of the recent Twitter reply system fiasco (see Twitter blog entries <a href="http://blog.twitter.com/2009/05/small-settings-update.html">1</a>, <a href="http://blog.twitter.com/2009/05/whoa-feedback.html">2</a>, <a href="http://blog.twitter.com/2009/05/we-learned-lot.html">3</a>, <a href="http://blog.twitter.com/2009/05/replies-kerfuffle.html">4</a> and related backlash spewed across the Internet), 
I recently joined <a href="http://friendfeed.com/pistos">FriendFeed</a> on recommendation by <a href="http://friendfeed.com/jaykul">Jaykul</a>.  It didn&#8217;t take long for me to be really impressed with this service, and for Twitter to look pretty rinky-dink in comparison.</p>

<p>If you just want a basic short message service with almost no frills, then sure, Twitter fits the bill.  But if you&#8217;re going to be using your communications service a lot, I think you might be pleasantly surprised, like I am, by all the great things FriendFeed is and does.  The following points may not provide enough justification for you to join FriendFeed (or completely switch over), but it is for me.</p>

<p><span id="more-338"></span>Of course, there are other features of FriendFeed beyond the ones I list here, but they are not the main selling points for me personally.  You can read FriendFeed&#8217;s own sales pitch on <a href="http://friendfeed.com/">the FriendFeed home page</a>.</p>

<h3>8. Quickly find friends already on FriendFeed</h3>

<p>While signing up, you are given the opportunity to find your friends who might already have FriendFeed accounts.  After one click (and giving my nick), it imported everyone I knew on Twitter who were already on FriendFeed.  Granted, Twitter has a similar on-join feature, but Twitter only imports from popular email services, whereas FriendFeed also imports from Twitter and Facebook.</p>

<h3>7. Comments are second class citizens</h3>

<p>I care about what I post to the Internet.  I believe in the quality of my postings.  I think that I owe it to my readership (and potential readership) to make everything I post on the net worth reading &#8212; something that would, if even just a little bit, enrich the life of the reader.  This holds especially true for this blog of mine, but also applies to my microblogging, even if only to a lesser extent.</p>

<p>Sometimes we want to reply to or acknowledge a tweet, or maybe just chuckle with the tweeter when they make a joke or witty remark.  On Twitter, what am I to do?  If I reply tweet with nothing but &#8220;@Jaykul lol&#8221;, I&#8217;d have degraded the quality of my tweetstream.  If I&#8217;m not willing to do that, then I have effectively been suppressed by the limitations of Twitter.</p>

<p>On FriendFeed, everyone has a main feed to which they can post messages, just like on Twitter or Facebook.  But over there, I can <em>comment</em> on Jaykul&#8217;s tweet with my one-word laugh message, and my main feed is not polluted.</p>

<h3>6. Like or Share, not retweet</h3>

<p>On FriendFeed, I can indicate I like something with a single click.  Then, everyone who cares to know (dependent on their account settings) can see what I marked.  The advantage there is that I don&#8217;t need to expend message text on attribution (&#8220;RT @nickname &#8230;&#8221;).  FriendFeed records and displays that metadata for me.  This character savings becomes more pronounced with further degrees of retweeting; you lose dozens of precious tweet characters when trying to preserve multiple attributions (&#8220;RT @nickname1 @nickname2 @nickname3&#8230;&#8221;).  Not so with FriendFeed.</p>

<p>Full-fledged sharing is also possible, to any of several other social sites, including Twitter, Facebook, Digg, Reddit and Delicious.</p>

<h3>5. Shortened URLs are expanded</h3>

<p>Those of you wary of (or downright averted to) URL shortening will be pleased to hear that FriendFeed expands URLs for you in your FriendFeed homepage.  If you don&#8217;t know what the problems with URL shorteners are, I&#8217;ll let you exercise your google fu and find out.</p>

<h3>4. Echo to Twitter</h3>

<p>FriendFeed allows you to echo your messages over to Twitter, so you still have a heartbeat over there while you wait for people to get FriendFeed accounts.  This of course removes the need to post the same message manually in both places.</p>

<h3>3. Aggregate other services, including Twitter</h3>

<p>FriendFeed has this great feature called &#8220;imaginary friends&#8221;.  Yeah, get the giggles out of your system from that name, then let&#8217;s move on.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   By creating an imaginary FriendFeed friend, you can in effect follow (subscribe) to their accounts on other services &#8212; 57 other services, to be exact, including Twitter, Flickr, Facebook, and many others.  This way, you can effectively import your Twitter friends who haven&#8217;t joined FriendFeed yet.  Once added as an imaginary friend, all their Twitter updates (or Flickr photos, or Facebook updates) appear in your FriendFeed home page.</p>

<p>Let&#8217;s recap the last two points again: You can post to Twitter from FriendFeed instead of at Twitter, and you can receive your Twitter friends&#8217; updates on FriendFeed instead of at Twitter.  In other words, it&#8217;s really starting to look like you don&#8217;t need Twitter much any more.  I only check it once in a while for direct messages, or for updates from people I haven&#8217;t turned into imaginary friends yet.</p>

<p>You can also follow any RSS feed with FriendFeed, which makes it a sort of primitive or summary-only RSS reader or aggregator.  I&#8217;m not an avid RSS collector (uses up too much time, a resource of which I have precious little to spare), so this suits me just fine.  For example, it&#8217;s allowed me to follow my personal github.com feed on FriendFeed instead of in a separate github browser tab.  Nice and tidy and unified.</p>

<h3>2. No 140 character limit</h3>

<p>For the most part, I do not communicate in short squirts.</p>

<p>I&#8217;ve lost count how many times I&#8217;ve tried to tweet something, then had to trim it down because of the 140 character limit, and also because I was trying not to break a message across two tweets.  One time I used &#8220;shorthand&#8221; like &#8220;2&#8243; for &#8220;to&#8221; or &#8220;u&#8221; for &#8220;you&#8221;, and was almost ashamed of myself for doing so.  Those of you that know me know that writing like that is <em>so</em> not me.</p>

<p>So, not having to restrict myself to the limits of an archaic technology was a huge selling point.  I don&#8217;t use my phone for text messaging, and I definitely don&#8217;t use it for updating Twitter, Facebook or FriendFeed.  So that 140 character limit feels annoying at best.</p>

<h3>1. Very high usability; nice design</h3>

<p>FriendFeed&#8217;s website is extremely well-designed.  There are many signs of the user interface being well thought out, and it&#8217;s clear that usability was given importance during development.  You should check it out for yourself, so you can experience what I&#8217;m talking about first-hand, but I can list a few items here.</p>

<p>The FriendFeed site strikes a great balance between AJAX versus full page loads.  You get a spinner (AJAX) or popup (JS/CSS) where appropriate; a full page refresh where appropriate.  This lends to a snappy and fluid user experience.</p>

<p>Hover over an account or group, and you get a handy JS/CSS popup that gives info and links for doing things or learning about that account or group.  This in effect reduces click depth, which gives the feel that the information you want is that much more accessible and readily available.</p>

<p>Text boxes start out small, but automatically expand in size as needed, when the text you type gets lengthy.  This lets the interface remain tidy and concise, but grow dynamically if there is a functional need.</p>

<p>When viewing a feed (such as the one on your personal FriendFeed home page), it updates in realtime with AJAX/JS effects.  Contrast that behaviour with the pages on Twitter.</p>

<p>FriendFeed is very customizable.  You can tweak notification settings, Twitter publishing preferences, and numerous other little things.  As with all software, options help to give a very satisfying experience, because the same software can be tailored to satisfy many different tastes and preferences.</p>

<p>Multiple messages are compressed into &#8220;see more&#8221; links, which further helps keep the interface tidy.  You can also Hide things with one click.  With another click, you can hide similar items, too.  For example, you might choose to hide a particular flickr photo of one friend &#8212; or go the distance and ignore their entire flickr photo stream.</p>

<p>When viewing someone or a group you might subscribe to, it tells you that the person posts &#8220;about 5 posts per day&#8221;.  This lets you quickly gauge how much activity the person or group would add to your feed.</p>

<h3>Conclusion</h3>

<p>In summary, I think these reasons combine to make switching from Twitter to FriendFeed very compelling.  FriendFeed offers everything Twitter does for me, and it does it much better, while also providing several enhanced features that Twitter does not provide.</p>

<p>If you&#8217;re a Twitter user, you at least owe it to yourself to make a FriendFeed account and test drive it.  Compare and make a decision for yourself.</p>

<ul>
<li><a href="http://friendfeed.com">http://friendfeed.com</a></li>
<li><a href="http://friendfeed.com/pistos">http://friendfeed.com/Pistos</a></li>
</ul>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F05%2F19%2F8-reasons-why-i-prefer-friendfeed-over-twitter%2F&amp;linkname=8%20reasons%20why%20I%20prefer%20FriendFeed%20over%20Twitter"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/05/19/8-reasons-why-i-prefer-friendfeed-over-twitter/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze 2009.05 released</title>
		<link>http://blog.purepistos.net/index.php/2009/05/06/ramaze-200905-released/</link>
		<comments>http://blog.purepistos.net/index.php/2009/05/06/ramaze-200905-released/#comments</comments>
		<pubDate>Wed, 06 May 2009 16:02:38 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[innate]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=270</guid>
		<description><![CDATA[Ramaze 2009.05 has been released.  This marks a new, brighter era in the Ramaze world.

Innate

For those of you that have not been following, manveru (Ramaze lead dev) had been brewing a new web framework core called Innate since the middle of last year.  As of today, Innate is pretty much done, and only [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Ramaze 2009.05 has been released.  This marks a new, brighter era in the Ramaze world.</p>

<h3>Innate</h3>

<p>For those of you that have not been following, manveru (Ramaze lead dev) had been brewing a new web framework core called Innate since the middle of last year.  As of today, Innate is pretty much done, and only sees minor updates.  Innate has its own <a href="http://github.com/manveru/innate/tree/master">repository on github</a>, where you can find a detailed README.  Innate is built on top of <a href="http://rack.rubyforge.org/">Rack</a>, the &#8220;web framework framework&#8221;, and acts as the core for Ramaze as of this Ramaze release.</p>

<h3>Upgrade carefully</h3>

<p>Because of this big change, Ramaze applications built with Ramaze 2009.03 or prior need non-trivial effort to port to 2009.05.  As such, <strong>proceed with caution when upgrading your gem</strong>, especially on production servers.  <span id="more-270"></span> You can install multiple Ramaze gem versions side by side, and then select a specific version in your applications as follows:</p>

<pre><code>require 'rubygems'
gem 'ramaze', '2009.03'
require 'ramaze'
</code></pre>

<p>Install or update Ramaze with</p>

<pre><code>gem install ramaze
</code></pre>

<p>The Ramaze team would like to apologize to those who unwittingly upgraded their Ramaze gems to 2009.04, which was essentially a beta release of the new Innate-cored Ramaze.  We understand and acknowledge that it may have caused some confusion for some, since legacy apps have a high chance of not working without modification, and also since nearly all online information written about Ramaze to date covers pre-Innate Ramaze.  We hope to rectify the situation with this release and announcement, and thank you for your understanding.</p>

<h3>Documentation</h3>

<p>As is the tradition in the Ramaze community, new code doesn&#8217;t come without a healthy dose of documentation.  manveru has taken a lot of time to document the way things work in Ramaze 2009.05.  Along with this release, he presents the fully updated, official online <a href="http://book.ramaze.net/">Ramaze book</a>.  It is quite detailed, and should help newcomers and old timers alike get to know the new Ramaze.  Although not complete at this time, it is receiving regular updates and additions.  The <a href="http://github.com/manveru/ramaze-book/tree/master">source of the book</a> is open source.</p>

<p>manveru has also updated his <a href="http://ramaze.net/todolist.html">Ramaze todo list tutorial</a> to work with 2009.05.</p>

<p>Don&#8217;t forget that the source code repositories of <a href="http://github.com/manveru/ramaze/tree/master">Ramaze</a> and <a href="http://github.com/manveru/innate/tree/master">Innate</a> also have abundant documentation in them.  Questions about Ramaze are sometimes answered by simply grepping the source code and reading the documentation, examples and tests.  Consult both Ramaze and Innate source.</p>

<p>It&#8217;s a good idea to bear in mind that anything written about Ramaze up to March 2009 may not accurately reflect Ramaze as it stands in April 2009 and onwards.</p>

<h3>Major changes</h3>

<p>Below are <em>some</em> of the changes introduced by the advance from 2009.03 to 2009.05.  Do not consider it exhaustive; you&#8217;d be better served checking other sources like <a href="http://book.ramaze.net">the Ramaze book</a>, and also hanging out <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">in IRC</a> so you can ask questions and receive live support.  <a href="http://groups.google.com/group/ramaze">The mailing list</a> is also a good way to get specific questions answered.</p>

<h4>Content representations</h4>

<p>Controllers can now <code>provide</code> one of multiple representations when responding to requests, based on conditions of your choosing.  For example, this new feature lets you serve a normal response to <code>/foo</code>, but a JSON response to <code>/foo.json</code>.  You can even use different templating engines for different wishes.  See <a href="http://book.ramaze.net/#_content_representations_2">the content representations section of the Ramaze book</a> and <a href="http://github.com/manveru/innate/blob/master/lib/innate/node.rb#L144-226">the source code of Innate::Node</a> for more details.</p>

<h4>Modes</h4>

<p>Ramaze applications can now run in different <a href="http://book.ramaze.net/#_ramaze_modes">modes</a>, such as :dev and :live.  You can make up custom modes since a mode is simply a nested array of Rack middleware.</p>

<h4>Layouts</h4>

<p>Layouts now reside in their own directory, <code>layout/</code>, distinct from the <code>view/</code> directory.  (As usual in the Ramaze world, these specific directories are only defaults.)  Layout specification can also now take a code block to control when a layout is applied.  See <a href="http://book.ramaze.net/#_usage_4">the layout section of the Ramaze book</a> for more details.</p>

<h4>Helpers</h4>

<p>The old link helper&#8217;s methods (A, R and Rs) have been deprecated and replaced by Innate&#8217;s link helper&#8217;s methods: a, r and rs.  They are mostly interchangeable, but the r methods can now also be called &#8220;off of&#8221; controllers:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">OtherController.<span style="color:#9900CC;">r</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:foo</span>, <span style="color:#ff3333; font-weight:bold;">:bar</span>, <span style="color:#ff3333; font-weight:bold;">:a</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:b</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#008000; font-style:italic;">#=&gt; URI('/other/foo/bar?a=b')</span></pre></div></div>


<p>The old partial helper has now been replaced by the render helper of Innate.  <a href="http://github.com/manveru/innate/blob/master/lib/innate/helper/render.rb">The source code for the render helper</a> is well-documented.  Refer to it for usage syntax and examples.</p>

<h4>Apps</h4>

<p>Ramaze Apps have been introduced (notice the spelling with a capital A).  A Ramaze App can be thought of as a namespace for controllers and options.  You can thus take related controllers, and then package, distribute and reuse them with relative ease.  An App is itself mapped to a path of your site, and can also use directories specific to it.  Some example code:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">module</span> Forumaze
  <span style="color:#9966CC; font-weight:bold;">class</span> MainController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Ramaze::Controller</span>
    map <span style="color:#996600;">'/'</span>, <span style="color:#ff3333; font-weight:bold;">:forumaze</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">class</span> AdminController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Ramaze::Controller</span>
    map <span style="color:#996600;">'/admin'</span>, <span style="color:#ff3333; font-weight:bold;">:forumaze</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
app = <span style="color:#6666ff; font-weight:bold;">Ramaze::App</span><span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:forumaze</span> <span style="color:#006600; font-weight:bold;">&#93;</span>
&nbsp;
<span style="color:#008000; font-style:italic;"># path on site (relative URL)</span>
app.<span style="color:#9900CC;">location</span> = <span style="color:#996600;">'/forum'</span>  
&nbsp;
<span style="color:#008000; font-style:italic;"># filesystem paths relative to current dir</span>
app.<span style="color:#9900CC;">options</span>.<span style="color:#9900CC;">publics</span> = <span style="color:#996600;">'forumaze/public'</span>  
app.<span style="color:#9900CC;">options</span>.<span style="color:#9900CC;">views</span> = <span style="color:#996600;">'forumaze/view'</span>
app.<span style="color:#9900CC;">options</span>.<span style="color:#9900CC;">layouts</span> = <span style="color:#996600;">'forumaze/layout'</span></pre></div></div>


<p>With the above code, hits to http://yourdomain.com/forum would be served by <code>Forumaze::MainController</code>, and hits to http://yourdomain.com/forum/admin would be served by <code>Forumaze::AdminController</code>.  Views would be taken from the directories <code>forumaze/view/</code> and <code>forumaze/view/admin</code>.  The same idea applies for static files and layouts of this App.</p>

<p>You can have multiple Controllers per App, and multiple Apps per Ramaze application.</p>

<h4><code>ramaze</code> binary</h4>

<p>The <code>ramaze</code> binary has been updated.  See <code>ramaze --help</code> and <a href="http://book.ramaze.net/#_the_ramaze_command">the ramaze command section in the Ramaze book</a>.</p>

<h4>Ezamar -> Etanni</h4>

<p>The old default templating engine, Ezamar, has been replaced by the Innate equivalent, <a href="http://github.com/manveru/innate/blob/master/lib/innate/view/etanni.rb">Etanni</a> (or the more powerful <a href="http://github.com/manveru/nagoro/tree/master">Nagoro</a>, if you choose).  Ezamar templates should be forward-compatible with Etanni, but Ezamar Elements have been removed.  To keep using Elements, use either Nagoro, which has Elements too, or the new render helper, which can accomplish the same thing in a different way.</p>

<h4>Miscellany</h4>

<p>The old <code>start.ru</code> Rackup file has been replaced with <code><a href="http://github.com/manveru/ramaze/blob/master/lib/proto/config.ru">config.ru</a></code>.  This is particularly important for those of you deploying with mod_rack (Passenger).</p>

<p><code>Ramaze::Global</code> has been removed and replaced with <code><a href="http://book.ramaze.net/#_configuration">Ramaze.options</a></code> which is intended to be a much better means of configuring Ramaze.  <code>Ramaze.options</code> is also extensible, so you can use it for custom configuration of your applications.</p>

<h3>Contributors</h3>

<p>Direct contributions to the code repository for this release came from the following people (listed alphabetically, nickname in parentheses):</p>

<h4>Innate</h4>

<ul>
<li>Sam Carr </li>
<li>Michael Fellinger (manveru)</li>
<li>Ryan Grove (rgrove)</li>
<li>Andreas Karlsson (jeltz)</li>
<li>(Pistos)</li>
<li>Tadahiko Uehara (kiko)</li>
<li>TJ Vanderpoel (bougyman)</li>
</ul>

<h4>Ramaze</h4>

<ul>
<li>Clive Crous (clive)</li>
<li>Michael Fellinger (manveru)</li>
<li>Ryan Grove (rgrove)</li>
<li>Aman Gupta (tmm1)</li>
<li>Andreas Karlsson (jeltz)</li>
<li>Victor Luft</li>
<li>(Pistos)</li>
<li>Tadahiko Uehara (kiko)</li>
<li>TJ Vanderpoel (bougyman)</li>
</ul>

<p>Of course, all the folks who use and test drive Ramaze every day also deserve thanks, not just for using it, but also for providing valuable feedback on previous releases ramping up to this one.</p>

<p>As usual, we&#8217;d love to hear from long-time users and newbies alike.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Stop by and say hello in <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">our IRC channel</a> (#ramaze on Freenode), or ask questions on <a href="http://groups.google.com/group/ramaze">our mailing list</a>.  We know converting old Ramaze apps may be challenging for some, but we&#8217;re here to help make the transition as smooth as possible for you.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>Enjoy this release, and keep on Ramazing!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F05%2F06%2Framaze-200905-released%2F&amp;linkname=Ramaze%202009.05%20released"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/05/06/ramaze-200905-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Chopin &#8211; Prelude Op. 28, No. 20 in C minor</title>
		<link>http://blog.purepistos.net/index.php/2009/05/03/chopin-prelude-op-28-no-20-in-c-minor/</link>
		<comments>http://blog.purepistos.net/index.php/2009/05/03/chopin-prelude-op-28-no-20-in-c-minor/#comments</comments>
		<pubDate>Sun, 03 May 2009 19:20:39 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[prelude]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=285</guid>
		<description><![CDATA[A short, sombre prelude by Chopin.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Prelude Op. 28, No. 4 in E minor
Chopin &#8211; Nocturne Op. 72, No. 1 in E minor
Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>A short, sombre prelude by Chopin.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F05%2F03%2Fchopin-prelude-op-28-no-20-in-c-minor%2F&amp;linkname=Chopin%20%26%238211%3B%20Prelude%20Op.%2028%2C%20No.%2020%20in%20C%20minor"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/05/03/chopin-prelude-op-28-no-20-in-c-minor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--chopin-prelude-op-28-no-20.mp3" length="1692316" type="audio/mpeg"/>
<itunes:duration>1:46</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Chopin &#8211; Prelude in A major, Op. 28, No. 7</title>
		<link>http://blog.purepistos.net/index.php/2009/05/01/chopin-prelude-in-a-major-op-28-no-7/</link>
		<comments>http://blog.purepistos.net/index.php/2009/05/01/chopin-prelude-in-a-major-op-28-no-7/#comments</comments>
		<pubDate>Sat, 02 May 2009 03:05:43 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[chopin]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[prelude]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=281</guid>
		<description><![CDATA[A very short prelude in A by my favourite composer.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Prelude Op. 28, No. 4 in E minor
Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major
Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>A very short prelude in A by my favourite composer.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F05%2F01%2Fchopin-prelude-in-a-major-op-28-no-7%2F&amp;linkname=Chopin%20%26%238211%3B%20Prelude%20in%20A%20major%2C%20Op.%2028%2C%20No.%207"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/01/12/chopin-nocturne-op-9-no-2-in-eb-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major'>Chopin &#8211; Nocturne Op. 9, No. 2 in Eb Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/05/chopin-mazurka-in-ab-major-op-24-no-3/' rel='bookmark' title='Permanent Link: Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3'>Chopin &#8211; Mazurka in Ab Major, Op. 24, No. 3</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/05/01/chopin-prelude-in-a-major-op-28-no-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/chopin/pistos--chopin-prelude-op-28-no-7.mp3" length="734354" type="audio/mpeg"/>
<itunes:duration>0:46</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Diakonos &#8211; version 0.8.8</title>
		<link>http://blog.purepistos.net/index.php/2009/04/03/diakonos-version-088/</link>
		<comments>http://blog.purepistos.net/index.php/2009/04/03/diakonos-version-088/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 19:17:26 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=226</guid>
		<description><![CDATA[Version 0.8.8 of Diakonos is now available.  This release delivers several new features, and also brings about a big change&#8230;

No more gem

Beginning with this release, I am doing something radical: I am not releasing Diakonos as a Ruby gem.  While that may seem strange to some, I think the move is not only [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.8 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.  This release delivers several new features, and also brings about a big change&#8230;</p>

<h4>No more gem</h4>

<p>Beginning with this release, I am doing something radical: I am not releasing Diakonos as a Ruby gem.  While that may seem strange to some, I think the move is not only justified, but better for Diakonos.<span id="more-226"></span></p>

<p>I don&#8217;t believe Diakonos has a tremendously large user base at the moment.  According to <a href="http://distrowatch.com/stats.php?section=popularity">DistroWatch</a> and <a href="http://rank.purepistos.net/">LinuxRank</a>, Ubuntu is easily the most popular Linux distribution.  If Diakonos is to gain any popularity, it behooves me to ensure that it installs onto and plays well with Ubuntu.</p>

<p>I noticed that <a href="http://packages.debian.org/unstable/text/diakonos">the Debian package for Diakonos</a> had fallen behind my upstream releases (it was stuck at 0.8.4).  I exchanged e-mails with Ralph Amissah, the maintainer of the Debian package (and, by extension, indirect maintaner of the Ubuntu package too), and was thereby informed that the inception of the new help system (introduced in 0.8.6) impeded the downstream updates.  In particular, Diakonos&#8217; downloading of configuration and help files for first time users was behaviour that ran contrary to Debian policy.</p>

<p>I think Debian and Ubuntu users who are not advanced Linux users would be more inclined to install packages via the apt system, as opposed to via RubyGems.</p>

<p>Furthermore, I have concluded that the RubyGems system is tailored much more towards libraries, and not applications.  It&#8217;s great for putting files where Ruby&#8217;s <code>require</code> and <code>load</code> statements can find them.  But it&#8217;s not so well suited to moving global configuration files into <code>/etc</code>, or system-wide documentation into <code>/usr/share/doc</code>.  <a href="http://www.ruby-forum.com/topic/55624#38790">I mumbled about this</a> over two years ago.  At first, I worked around the problem by having Diakonos installed via RubyGems, and then downloading configuration files (and, later, help files) from the Internet when the user first runs Diakonos.  But, as I&#8217;ve mentioned, this prevented smooth inclusion into the Debian package repositories.</p>

<p>RubyGems is focused on letting Ruby developers disseminate their libraries to other Ruby developers; Diakonos is an end-user application.  That it is written in Ruby is secondary and peripheral; it is not my intention to present a cute novelty to the amusement and delight of a fraction of the developers of a subculture programming language.  My goal is to create the most user-friendly console editor for Linux (&#8220;a Linux editor for the masses&#8221;).</p>

<p>In light of these facts, I elected to abandon the RubyGems system in favour of a custom installer (<code>install.rb</code> in the package).  This installer would allow a distro package maintainer to install Diakonos to specific locations of his or her choosing in the filesystem.  I envision that package maintainers for all distros should have little difficulty using it to create or update their packages.  Of course, it is easy to use for the end user himself, as well.  It can be used to install Diakonos completely in userspace (i.e. somewhere under a user&#8217;s home directory, without the need for root/sudo privileges).</p>

<p>The new package (simply a tarball) contains everything needed to run Diakonos, including default configuration files and a full set of help files.  Diakonos no longer accesses the Internet for these like it used to in previous versions.</p>

<p>Configuration is loaded from the system-wide location (specified during installation), but user-specific overrides are (as before) loaded from <code>~/.diakonos/diakonos.conf</code>.</p>

<h4>Configuration inheritance</h4>

<p>Configuration settings can now be inherited (cascaded).  Simply use an equals sign (=) to set one setting to the value of another.</p>

<pre><code>one.setting = another.setting
</code></pre>

<p>For an example, have a look at <a href="http://github.com/Pistos/diakonos/blob/c9a034cb79fe64f3347dbe807e467e7e4b8f5015/diakonos.conf#L671-675">the Ruby language definition in the default config file</a>.  See how <a href="http://github.com/Pistos/diakonos/blob/c9a034cb79fe64f3347dbe807e467e7e4b8f5015/diakonos.conf#L467-477">the shared settings are defined earlier in the file</a>.</p>

<p>This inheritance will work for any setting, not just formatting.  The important thing to remember is that Diakonos will parse configuration files top to bottom, and visit each <code>include</code>d file in the order the <code>include</code> directives are encountered, with a depth-first strategy.  So you should define ancestor settings before descendant settings.</p>

<h4>Block selection</h4>

<p>You can now switch between block (columnar) selection and normal (flow) selection.  Default keychains: &lt;Alt-Shift-M, B&gt; for block, &lt;Alt-Shift-M, N&gt; for normal.  Mnemonic: M for Mark, B for Block, N for Normal.</p>

<h4>Line numbering</h4>

<p>Default keychord &lt;Alt-Shift-L&gt; can be used to toggle line numbering on and off.  Line numbers appear in a left-side margin.  Enable line numbering permanently by setting <code>view.line_numbers</code> to <code>true</code> in your config.  Set <code>view.line_numbers.width</code> to the number of columns to use for the line numbering margin.  <code>view.line_numbers.number_format</code> is the setting to use to define a <code><a href="http://www.ruby-doc.org/core-1.9/classes/Kernel.html#M006076">sprintf</a></code> format for the line numbers.  Set the colour and brightness with <code>view.line_numbers.format</code>.</p>

<h4>Code block navigation</h4>

<p>A cool thing I&#8217;ve added in this release is code block navigation.  Using Ctrl-PageDown, you can jump to the next code block of the same indentation level as the current line.  Ctrl-PageUp goes back in the opposite direction (up or previous block).  You might use this to easily browse: the methods of a class; or the different <code>when</code> clauses of a Ruby <code>case</code> expression; or the components of an <code>if-elsif-else</code> tree; or the rules of a CSS stylesheet; and so on.  Diakonos will automatically limit the extent of the navigation, so if you start your browsing within an <code>if-elsif</code> tree, your cursor won&#8217;t jump outside that tree if you press Ctrl-PageDown too many times.</p>

<p>Alt-PageDown brings the cursor one block level deeper; Alt-PageUp brings you out one level.</p>

<h4>Column markers</h4>

<p>You can now define column markers using the <code>view.column_markers.*</code> settings.  I&#8217;ve provided an example in the default config:</p>

<pre><code>view.column_markers.margin.column 80
view.column_markers.margin.format 9
</code></pre>

<p>Uncommenting or adding these lines would set up a column marker named &#8220;margin&#8221;.  The name &#8220;margin&#8221; is arbitrary; use whatever names you want for your markers.  The &#8220;margin&#8221; marker would highlight the 80th column using the format code 9 (white on red in the default 16-colour configuration).</p>

<p>You might use such a column marker as a visual cue to help you not exceed a certain line length.  You can set up as many column markers as you like.</p>

<h4>Remove word from input line</h4>

<p>Pressing Ctrl-W on the input line will now delete the last word on the line.  I mainly included this to lop off file path components when opening new files or grepping directories.</p>

<h4>Ruby 1.9 and 1.8 support</h4>

<p>Ruby 1.9 support is even better now.  There are no known issues with Diakonos running under Ruby 1.9.1.  If you encounter anything, please <a href="http://linis.purepistos.net/ticket/list/Diakonos">let me know</a>.</p>

<p>As I move forward with development, I am preferring 1.9 styles and constructions where there is a choice.  As such, some functions of Diakonos may no longer function under Ruby 1.8.  I encourage you to install Ruby 1.9 if you have not already, and to keep both versions concurrently installed on your systems.  The Ruby community benefits when people move forward to adopt and use this latest stable release of Ruby.</p>

<p>A corollary of running under 1.9 is the ability to open and edit files with encodings other than ASCII.  The little test files I opened were handled by Diakonos without difficulty.  I could insert and delete UTF-8 characters and save the file.  Any real world usage (testing) of Diakonos with non-ASCII files is appreciated!</p>

<p>Also, don&#8217;t forget that things run faster under Ruby 1.9, and Diakonos is no exception!</p>

<h4>Et cetera</h4>

<p>Several bugs were fixed (see the git commit log for details).  If you subscribed to the particular <a href="http://linis.purepistos.net/ticket/list/Diakonos">LinisTrac tickets</a> in question, you would have already been notified.</p>

<p>The rest of the changes are described in this version&#8217;s full <a href="http://github.com/Pistos/diakonos/tree/v0.8.8/CHANGELOG">changelog</a>:</p>

<ul>
<li>New installation and uninstallation method: tarball + install.rb.</li>
<li>Added configuration setting inheritance.</li>
<li>Added block selection mode (Alt-Shift-M B; Alt-Shift-M N).</li>
<li>Added line numbering settings.</li>
<li>Added spawn function.</li>
<li>Added go_block_previous, go_block_next (Ctrl-PageUp, Ctrl-PageDown).</li>
<li>Added go_block_outer, go_block_inner (Alt-PageUp, Alt-PageDown).</li>
<li>&#8220;Remove word&#8221; functionality (Ctrl-W) added to readline.</li>
<li>Added find.show_context_after setting.</li>
<li>Added view.column_markers.</li>
<li>Added lang.____.indent.not_indented setting.</li>
<li>Introduced $d shell variable: current buffer&#8217;s directory.</li>
<li>$f and $d now expand to absolute paths.</li>
<li>delete_to and delete_to_and_from can now operate over multiple lines.</li>
<li>delete_to_and_from can now delete between matching brackets.</li>
<li>Added git diff (F9).</li>
<li>Ruby 1.9 support smoothed out.  Ruby 1.8 support being deprecated.</li>
<li>Support for non-ASCII encodings tentatively confirmed.</li>
<li>Several bugs fixed.</li>
<li>Help files updated.</li>
</ul>

<p>As usual, report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes">visit me in IRC</a>.  If you like Diakonos, please consider <a href="http://www.pledgie.com/campaigns/3542">making a small donation</a>.</p>

<p>Enjoy version 0.8.8!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F04%2F03%2Fdiakonos-version-088%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.8"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/04/03/diakonos-version-088/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Debussy &#8211; R&#234;verie</title>
		<link>http://blog.purepistos.net/index.php/2009/03/18/debussy-reverie/</link>
		<comments>http://blog.purepistos.net/index.php/2009/03/18/debussy-reverie/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 03:50:56 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=250</guid>
		<description><![CDATA[Another dreamy, reflective, cloudy piece by Claude Debussy.

Read more about my piano recording series here.




Related posts:Chopin &#8211; Nocturne Op. 72, No. 1 in E minor
Chopin &#8211; Polonaise Op. 40, No. 1 in A Major
Chopin &#8211; Prelude Op. 28, No. 4 in E minor



Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>Another dreamy, reflective, cloudy piece by Claude Debussy.</p>

<p>Read more about my piano recording series <a href="http://blog.purepistos.net/index.php/piano/">here</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F03%2F18%2Fdebussy-reverie%2F&amp;linkname=Debussy%20%26%238211%3B%20R%26ecirc%3Bverie"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2010/02/22/chopin-polonaise-op-40-no-1-in-a-major/' rel='bookmark' title='Permanent Link: Chopin &#8211; Polonaise Op. 40, No. 1 in A Major'>Chopin &#8211; Polonaise Op. 40, No. 1 in A Major</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/03/18/debussy-reverie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/debussy/pistos--debussy-reverie.mp3" length="3959327" type="audio/mpeg"/>
<itunes:duration>4:07</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
		<item>
		<title>Diakonos &#8211; version 0.8.7</title>
		<link>http://blog.purepistos.net/index.php/2009/02/22/diakonos-version-087/</link>
		<comments>http://blog.purepistos.net/index.php/2009/02/22/diakonos-version-087/#comments</comments>
		<pubDate>Mon, 23 Feb 2009 03:35:35 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=207</guid>
		<description><![CDATA[Version 0.8.7 of Diakonos is now available.  Install by gem install diakonos.  This version brings several new features and more bug fixes.

strip_trailing_whitespace_on_save

A strip_trailing_whitespace_on_save setting was added, defaulting to true.  I&#8217;ve joined the camp of those who believe that trailing whitespace doesn&#8217;t belong in source control repositories (due to diff false positives).

Sessions

I&#8217;ve added [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.7 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.  Install by <code>gem install diakonos</code>.  This version brings several new features and more bug fixes.</p>

<h4>strip_trailing_whitespace_on_save</h4>

<p>A strip_trailing_whitespace_on_save setting was added, defaulting to true.  I&#8217;ve joined the camp of those who believe that trailing whitespace doesn&#8217;t belong in source control repositories (due to diff false positives).</p>

<h4>Sessions</h4>

<p>I&#8217;ve added sessions to Diakonos, and use them all the time now.  Name your session by starting diakonos with a -s option:</p>

<pre><code>diakonos -s my-website
</code></pre>

<p>The default configuration will show the session name in the bottom right.  If you close Diakonos and reopen it with the same session name, it will reopen all the same files as were open when you closed it.</p>

<p>If you open Diakonos without a session name, it will still maintain an anonymous session until you quit.  If Diakonos or your computer should crash during your session, you can start up Diakonos and it will prompt you to restore any sessions that were not closed gracefully.</p>

<h4>Grep as you type</h4>

<p>The previous release of Diakonos saw the inclusion of &#8220;find as you type&#8221;.  This version provides grep as you type.  Behold the coolness via this mini screencast:</p>

<p><center><OBJECT CLASSID="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" WIDTH="360" HEIGHT="321" CODEBASE="http://active.macromedia.com/flash5/cabs/swflash.cab#version=5,0,0,0">
<PARAM NAME=movie VALUE="grep-as-you-type.swf">
<PARAM NAME=play VALUE=true>
<PARAM NAME=loop VALUE=false>
<PARAM NAME=quality VALUE=low>
<EMBED SRC="/wp-content/uploads/diakonos/grep-as-you-type.swf" WIDTH=360 HEIGHT=321 quality=low loop=false TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
</EMBED>
</OBJECT>
</center></p>

<h4>delete_to</h4>

<p>Being forced to use vi on occasion at work, I&#8217;ve become acquainted with at least one neat thing: You can press &#8220;dt&#8221; in vi to &#8220;delete till&#8221;.  So I brought this functionality over to Diakonos.  Type <code>Ctrl-D-T, "</code> to change this:</p>

<pre style="background-color: #222222; color: #FFFFFF">
 some_method( "here is a <span style="background-color: #CCCCCC; color: #000000">s</span>tring", 3 )
</pre>

<p>to this:</p>

<pre style="background-color: #222222; color: #FFFFFF">
 some_method( "here is a <span style="background-color: #CCCCCC; color: #000000">"</span>, 3 )
</pre>

<p>Type <code>Ctrl-D-I, "</code> to change this:</p>

<pre style="background-color: #222222; color: #FFFFFF">
 some_method( "here is a <span style="background-color: #CCCCCC; color: #000000">s</span>tring", 3 )
</pre>

<p>to this:</p>

<pre style="background-color: #222222; color: #FFFFFF">
 some_method( "<span style="background-color: #CCCCCC; color: #000000">"</span>, 3 )
</pre>

<h4>custom.conf</h4>

<p>The default <code>diakonos.conf</code> configuration file now has an <code>include custom.conf</code> directive.  This lets you keep your custom Diakonos configurations in <code>~/.diakonos/custom.conf</code> while allowing you to regularly upgrade <code>diakonos.conf</code> with each new Diakonos version.</p>

<h4>Ruby 1.9 compatibility</h4>

<p>Version 0.8.7 marks the first version of Diakonos that can run under Ruby 1.9.  Diakonos 0.8.7 will also run under Ruby 1.8.6.  Please be advised that I am tentatively planning on dropping Ruby 1.8.x support beginning with the next Diakonos version.</p>

<h4>Changelog</h4>

<p>Here is this version&#8217;s full <a href="http://github.com/Pistos/diakonos/tree/v0.8.6/CHANGELOG">changelog</a>:</p>

<ul>
<li>MRU buffer history added.</li>
<li>strip_trailing_whitespace_on_save setting added.</li>
<li>Sessions (named and unnamed) added.</li>
<li>grep as you type added.</li>
<li>delete_to added.</li>
<li>delete_to_and_from added.</li>
<li>find.return_on_abort setting added.</li>
<li>Makefile config added.</li>
<li>Markdown config added.</li>
<li>Sass config added.</li>
<li>Now including custom.conf from default diakonos.conf.</li>
<li>Help files updated.</li>
<li>Some Ruby 1.9 compatibility introduced.</li>
<li>Lots of code refactoring done.</li>
<li>Numerous little adjustments and fixes made.</li>
</ul>

<p>Report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes">visit me in IRC</a>!  Enjoy this release.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F02%2F22%2Fdiakonos-version-087%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.7"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/02/22/diakonos-version-087/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ramaze 2009.02 released</title>
		<link>http://blog.purepistos.net/index.php/2009/02/14/ramaze-200902-released/</link>
		<comments>http://blog.purepistos.net/index.php/2009/02/14/ramaze-200902-released/#comments</comments>
		<pubDate>Sat, 14 Feb 2009 05:22:32 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=200</guid>
		<description><![CDATA[Ramaze 2009.02 has just been released.  There are just a few changes since 2009.01:


Redirection within https fixed.
flash.delete now fully deletes from flash.
Subclass controllers now properly inherit the template engine of the parent controller class.
Ruby 1.9 compatibility improved.


manveru has always been conscientious about Ruby 1.9 compatibility in Ramaze (indeed, in all his projects), so Ramaze [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Ramaze 2009.02 has just been released.  There are just a few changes since 2009.01:</p>

<ul>
<li>Redirection within https fixed.</li>
<li>flash.delete now fully deletes from flash.</li>
<li>Subclass controllers now properly inherit the template engine of the parent controller class.</li>
<li>Ruby 1.9 compatibility improved.</li>
</ul>

<p>manveru has always been conscientious about Ruby 1.9 compatibility in Ramaze (indeed, in all his projects), so Ramaze had already been considered 1.9-compatible for some time.  With <a href="http://www.ruby-lang.org/en/news/2009/01/30/ruby-1-9-1-released/">the recent release of Ruby 1.9.1</a>, though, a fresh problem crawled out of the woodwork.  This release addresses the issue; see <a href="http://groups.google.com/group/ramaze/browse_thread/thread/1f1124d084e5d061">the mailing list thread</a> for details.</p>

<p>As some of you can probably appreciate, <a href="http://www.rubyinside.com/23-useful-ruby-19-links-and-resources-1498.html">1.9 compatibility is a non-trivial assignment</a>.  If you encounter any sort of problems using Ruby 1.9.1+, please don&#8217;t hesitate to <a href="http://groups.google.com/group/ramaze">let us know</a>.</p>

<p>Contributions to this release came from the following people (listed alphabetically):</p>

<ul>
<li>Andreas Karlsson (jeltz)</li>
<li>Michael Fellinger (manveru)</li>
<li>(Pistos)</li>
<li>Riku Raisaenen (rikur)</li>
<li>Sean Lai</li>
</ul>

<p>Install or update Ramaze with</p>

<pre><code>gem install ramaze
</code></pre>

<p>As usual, we&#8217;d love to hear from long-time users and newbies alike.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Stop by and say hello in <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">our IRC channel</a> (#ramaze on Freenode), or ask questions on <a href="http://groups.google.com/group/ramaze">our mailing list</a>.</p>

<p>And don&#8217;t forget that the next generation of Ramaze, with an &#8220;Innate&#8221; core, is on the horizon, with several features and improvements.  In the mean time, enjoy this release!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F02%2F14%2Framaze-200902-released%2F&amp;linkname=Ramaze%202009.02%20released"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/02/14/ramaze-200902-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Selfmarks &#8211; anti-social bookmarking</title>
		<link>http://blog.purepistos.net/index.php/2009/02/06/selfmarks-anti-social-bookmarking/</link>
		<comments>http://blog.purepistos.net/index.php/2009/02/06/selfmarks-anti-social-bookmarking/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 21:01:58 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[anti]]></category>
		<category><![CDATA[bookmarking]]></category>
		<category><![CDATA[m4dbi]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[social]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=188</guid>
		<description><![CDATA[I&#8217;d like to introduce a project I&#8217;ve been working on for the past week.

From the Selfmarks site:


  Selfmarks is anti-social bookmarking for the technically endowed. Trouble-free bookmarking for geeks. Bookmarking without the centralization handcuffs; you take all the credit (and blame).


I used Diigo to manage all my bookmarks for the past couple years, and [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d like to introduce a project I&#8217;ve been working on for the past week.</p>

<p>From <a href="http://sm.purepistos.net">the Selfmarks site</a>:</p>

<blockquote>
  <p>Selfmarks is anti-social bookmarking for the technically endowed. Trouble-free bookmarking for geeks. Bookmarking without the centralization handcuffs; you take all the credit (and blame).</p>
</blockquote>

<p>I used <a href="http://www.diigo.com">Diigo</a> to manage all my bookmarks for the past couple years, and for the most part the service has been decent.  I would still recommend them as a good site for social bookmarking.  But now and again, I would find their servers responding very slowly, and I just got fed up with that, because I never really used the &#8220;social&#8221; part of social bookmarking.  All I really wanted was a place on the Internet I could put my bookmarks.</p>

<p>So, after one more episode of dissatisfactory service, I finally cracked and started writing up my own bookmarking site.</p>

<p>Selfmarks is written in <a href="http://www.ruby-lang.org/en/">Ruby</a>, using the <a href="http://ramaze.net">Ramaze</a> web framework.  I access a <a href="http://www.postgresql.org/">PostgreSQL</a> database using <a href="http://purepistos.net/m4dbi">M4DBI</a> for ORM.  Thanks go to <a href="http://www.creations.ro">Alexut</a> for the Selfmarks logo.</p>

<p>Selfmarks is OpenID-enabled, so go ahead and use your OpenID to instantly create an account and play with the site.  You can import your bookmarks in <a href="http://delicious.com/">delicious</a> format.</p>

<p>The project is open source; grab it <a href="http://github.com/Pistos/selfmarks/tree/master">from github</a>, or</p>

<pre><code>git clone git://github.com/Pistos/selfmarks.git
</code></pre>

<p>Installing Selfmarks for oneself should only be a mild challenge for a seasoned programmer.  There has already been one other successful installation by an experienced Rails and Ruby dev.</p>

<p>Let me know what you think!  Leave a comment on this blog post, or <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes,%23ramaze">chat with me on FreeNode</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F02%2F06%2Fselfmarks-anti-social-bookmarking%2F&amp;linkname=Selfmarks%20%26%238211%3B%20anti-social%20bookmarking"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/02/06/selfmarks-anti-social-bookmarking/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Comet with Ramaze</title>
		<link>http://blog.purepistos.net/index.php/2009/01/27/comet-with-ramaze/</link>
		<comments>http://blog.purepistos.net/index.php/2009/01/27/comet-with-ramaze/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 15:01:01 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[push]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=143</guid>
		<description><![CDATA[In this blog post, I describe how to do (one kind of) Comet in a Ramaze web application using jQuery.  I begin by glossing over Comet, what problem Comet tries to solve, and some other related concepts.  Those of you already familiar with Comet can jump right to
the example.

To get the most out [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>In this blog post, I describe how to do (one kind of) Comet in a <a href="http://ramaze.net">Ramaze</a> web application using <a href="http://jquery.com">jQuery</a>.  I begin by glossing over Comet, what problem Comet tries to solve, and some other related concepts.  Those of you already familiar with Comet can jump right to
<a href="#example">the example</a>.</p>

<p>To get the most out of this article, you should be comfortable with Ramaze, HTML and Javascript.  If you need to get up to speed on Ramaze, learn more <a href="http://ramaze.net/learn">at the Ramaze website</a>.</p>

<p><span id="more-143"></span></p>

<h3>What&#8217;s Comet?</h3>

<p>From <a href="http://en.wikipedia.org/wiki/Comet_(programming">the Wikipedia article on Comet in web programming</a>):</p>

<blockquote>
  <p>In web development, Comet is a neologism to describe a web application model in which a long-held HTTP request allows a web server to push data to a browser, without the browser explicitly requesting it. Comet is an umbrella term for multiple techniques for achieving this interaction. All methods have in common that they rely on browser-native technologies such as JavaScript</p>
</blockquote>

<h3>Why Comet?</h3>

<p>In traditional web applications, the process flow is:</p>

<hr />

<p><img src="/wp-content/uploads/ramaze-comet-example/traditional-flow.png" alt="Traditional web app flow" /></p>

<hr />

<ol>
<li>time passes until the web browser (the client) wants data</li>
<li>client requests data from server</li>
<li>server gives data to client</li>
<li>repeat from step 1</li>
</ol>

<p>As web developers got more clever, they wondered how they might get the server to give data to the client when the <em>server</em> wanted to give it, not when the client wanted to get it.  So they came up with a flow like this:</p>

<hr />

<p><img src="/wp-content/uploads/ramaze-comet-example/naive-polling.png" alt="Naive polling flow" /></p>

<hr />

<ol>
<li>client asks for data from server, if any (client polls server)</li>
<li>if server doesn&#8217;t have data ready, server tells client no data is available</li>
<li>client waits a &#8220;short while&#8221;; repeats from step 1</li>
<li>if server has data, server gives data to client</li>
<li>repeat from step 1</li>
</ol>

<p>However, when developing an application with this design, you had to make a tradeoff:</p>

<ul>
<li>Polling frequently puts unnecessary load on the server</li>
<li>Polling infrequently causes the client interface to lag behind the actual data source</li>
</ul>

<p>Comet tries to address both problems, so no tradeoff has to be made.  With Comet, you can poll infrequently but still get the data to the client very soon after the server is ready to give it.</p>

<h3>Two kinds of Comet</h3>

<p>There are roughly two kinds of Comet:</p>

<h4>Streaming</h4>

<p>In streaming Comet, a connection between client and server is made, and data is pushed from server to client whenever it is available.  The connection always remains open, even after each bit of data is transferred.  The example in this article does not implement this type of Comet.</p>

<h4>Long polling</h4>

<p>Long polling works like the &#8220;bad&#8221; polling design, except the server does not respond to the client until the data is ready.  As already mentioned, this results in fewer network connections while still maintaining low latency.</p>

<hr />

<p><img src="/wp-content/uploads/ramaze-comet-example/long-polling.png" alt="Long polling flow" /></p>

<hr />

<h2 id="example">A Comet example in Ramaze</h2>

<p>I&#8217;ll exemplify Comet in Ramaze by building a web application that tails a file on the server and displays the lines on the web page as soon as they are available.  The full source code can be found <a href="http://github.com/Pistos/ramaze-comet-example/tree/master">on github</a>.  You are advised to clone or download from there so you can follow along.  I will not go over every line of code in this article.</p>

<p>I also make use of another data producer which manveru provided.  The application demonstrates that the very same process and implementation can be applied with different producers.</p>

<h3>Client</h3>

<p><a href="http://github.com/Pistos/ramaze-comet-example/blob/8336ca003822eade42ee1609c4859f55747501c6/view/tail.xhtml">The web page code</a> is very simple.  It has this body:</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h4</span>&gt;</span>Tailer:<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h4</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">textarea</span> <span style="color: #000066;">id</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;tailer&quot;</span> <span style="color: #000066;">rows</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;16&quot;</span> <span style="color: #000066;">cols</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;80&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">textarea</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span></pre></div></div>


<p>We&#8217;ll use a &lt;textarea&gt; to hold the file lines, and give it an id, <code>tailer</code>.</p>

<p>In <a href="http://github.com/Pistos/ramaze-comet-example/blob/8336ca003822eade42ee1609c4859f55747501c6/public/main.js">the Javascript</a>, we have a function called <code>get_more_lines</code>.  The client:</p>

<ol>
<li>calls this function which</li>
<li>waits for data</li>
<li>receives the data</li>
<li>appends the data into the &lt;textarea&gt;</li>
<li>calls the function again (repeats from step 1)</li>
</ol>

<h3>Server</h3>

<p><a href="http://github.com/Pistos/ramaze-comet-example/blob/8336ca003822eade42ee1609c4859f55747501c6/view/tail.xhtml">The interface page</a> (located at the path <code>/tail</code>) is just static HTML, so it needs no controller code.  But let&#8217;s examine <a href="http://github.com/Pistos/ramaze-comet-example/blob/8336ca003822eade42ee1609c4859f55747501c6/src/main.rb">the controller code</a> to see how the server side gives data to clients.</p>

<p>As you saw <a href="http://github.com/Pistos/ramaze-comet-example/blob/8336ca003822eade42ee1609c4859f55747501c6/public/main.js#L17">in the client code</a>, the tailer data is retrieved from the path <code>/next_tailer_lines</code>.  In the controller, <code>next_tailer_lines</code> calls a more generic <code>next_lines</code> method, which has this code in it:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">60.<span style="color:#9900CC;">times</span> <span style="color:#9966CC; font-weight:bold;">do</span>
  lines = producer.<span style="color:#9900CC;">new_lines</span><span style="color:#006600; font-weight:bold;">&#40;</span> session.<span style="color:#9900CC;">session_id</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> lines.<span style="color:#9900CC;">any</span>?
    <span style="color:#6666ff; font-weight:bold;">Ramaze::Log</span>.<span style="color:#9900CC;">debug</span> <span style="color:#996600;">&quot;New data!&quot;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> lines
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#6666ff; font-weight:bold;">Ramaze::Log</span>.<span style="color:#9900CC;">debug</span> <span style="color:#996600;">&quot;Waiting for data...&quot;</span>
  <span style="color:#CC0066; font-weight:bold;">sleep</span> <span style="color:#006666;">1</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>When there is a request for <code>next_lines</code>, the server checks the server-side producer for more data.  If there is no new data, rather than returning any response to the client, the server continues to poll the producer.</p>

<p>The key thing to note here is that the server is doing the polling server-side.  The client is merely waiting for the server to respond to the single request &#8212; no polling is going on between client and server while data is unavailable.  Because the polling is server-side, it is much cheaper, so we can be much more liberal with the polling frequency.</p>

<p>If and when the data becomes available from the producer, the server gives that data to the client right away.</p>

<p>On a basic level, that&#8217;s all you need for Comet!</p>

<ol>
<li>Server-side producer(s)</li>
<li>URI for the client to retrieve data from</li>
<li>Client-side &#8220;request and consume&#8221; loop</li>
<li>On request, server polls data source (producer), responding only when ready</li>
</ol>

<p>Try out this example yourself!  Grab the code with</p>

<pre><code>git clone git://github.com/Pistos/ramaze-comet-example.git
</code></pre>

<p>(or download it with the &#8220;download&#8221; button
 <a href="http://github.com/Pistos/ramaze-comet-example/tree/master">on github</a>).</p>

<p>Install the <code>file-tail</code> gem, and then open up a <code>ramaze-comet-example.log</code> file in the same directory as <code>start.rb</code>.  Fill it with some sample text.  Then run</p>

<pre><code>ruby start.rb
</code></pre>

<p>and browse to <a href="http://localhost:7001/tail">http://localhost:7001/tail</a>.  You should see the last 10 lines of your <code>ramaze-comet-example.log</code> file.  Now, with the web page open, add some more lines to the file (don&#8217;t forget to save if you&#8217;re using an editor to add lines), and then look at your browser; the new lines should appear (after a tiny delay).  And of course, since this uses AJAX, there is no need to refresh the page to see new data.</p>

<p>You can also experiment by changing the filepath in the source code to point to a real log file of your own.</p>

<h3>Details</h3>

<h4>Server-side timeout</h4>

<p>You may wonder why we <a href="http://github.com/Pistos/ramaze-comet-example/blob/8336ca003822eade42ee1609c4859f55747501c6/src/main.rb#L11">loop only 60 times</a> instead of infinitely polling for data.  While infinite polling is possible, it is not practical to employ because the server would continue to poll even after the client disconnects (such as when the browser tab is closed, or the page is refreshed).  It&#8217;s better to time out the polling and return empty data.  If the client is gone, the empty data is sent harmlessly into the ether, communications cease, and the server will stop polling.  If the client is still around, it will reinitiate a fresh network connection, and polling will continue.  But that&#8217;s why this technique is called &#8220;long polling&#8221; and not &#8220;infinitely long polling&#8221;.  In contrast with the naive polling implementation, the client-side polls are less frequent and their durations are much longer.</p>

<p>In this example, we loop 60 times, waiting one second per iteration.  You can obviously tweak these numbers for your own needs in your application; sleep less or more; loop fewer or more times for a shorter or longer server-side timeout.  The tradeoff with longer server-side timeouts is that your application is doing a little extra work for nothing for clients that have disconnected.</p>

<h4>Browser connection limit</h4>

<p>You should also be aware that most browsers limit the number of connections to a server (typically only 2).  If you keep one connection open for Comet, that only leaves one other one available, so normal operations like parallel fetching of images, CSS files, etc. will be slowed down.  That also limits you to only one Comet connection.</p>

<p>A common workaround for this issue is to create subdomains on a domain (usually pointing to the same server as the domain), so the browser is tricked into thinking it is making connections to different servers; each domain or subdomain is given a full set of connections to work with.  You could, for example, have a subdomain comet.mydomain.com for Comet connections, and use mydomain.com for normal HTTP requests.</p>

<h4>The Javascript in detail</h4>

<p>For those who are interested, I&#8217;ll explain the Javascript in greater detail.  Let&#8217;s look at
<a href="http://github.com/Pistos/ramaze-comet-example/blob/c28c972d05827dffeeb1804768b1a71aba3a7546/public/main.js#L1">the get_more_lines function</a>:</p>


<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span>
    data_uri<span style="color: #339933;">,</span>
    <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span> data <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066; font-weight: bold;">if</span><span style="color: #009900;">&#40;</span> data <span style="color: #339933;">!=</span> <span style="color: #3366CC;">''</span> <span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            $<span style="color: #009900;">&#40;</span> receiver_id <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">append</span><span style="color: #009900;">&#40;</span> data <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #003366; font-weight: bold;">var</span> receiver <span style="color: #339933;">=</span> $<span style="color: #009900;">&#40;</span> receiver_id <span style="color: #009900;">&#41;</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span> <span style="color: #CC0000;">0</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            receiver.<span style="color: #660066;">scrollTop</span> <span style="color: #339933;">=</span> receiver.<span style="color: #660066;">scrollHeight</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        setTimeout<span style="color: #009900;">&#40;</span> get_more_lines<span style="color: #009900;">&#40;</span> receiver_id<span style="color: #339933;">,</span> data_uri <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>


<p>The first line is the call to jQuery&#8217;s <a href="http://docs.jquery.com/Ajax/jQuery.get#urldatacallbacktype">get</a> function.  This issues an HTTP GET request.  The first argument is the URI to call.  The second argument is a callback function used to process the server response.</p>

<p>Inside the callback function, we have a conditional to check whether (a) we actually got data, or (b) the server timed out waiting for the producer to produce new data.  If we have data, then we <code>append</code> the data to the jQuery element (or document element, if you prefer) which we reference by the given id string.  Then we use <code>scrollTop</code> and <code>scrollHeight</code> to auto-scroll the &lt;textarea&gt; to the bottom as new lines are fetched.</p>

<p>The last line of the callback function calls <code>get_more_lines</code> again.  The reason we use <code>setTimeout</code> is because if we called <code>get_more_lines</code> directly, that would be recursion, which runs the risk of consuming memory as each step of recursion grows the call stack.</p>

<h4>Alternative producer</h4>

<p>Browse to <a href="http://localhost:7001/chat">http://localhost:7001/chat</a> to see the same Comet code work with a different data producer.  New &#8220;chat&#8221; lines are added to a channel at random intervals, and the browser is updated with the new lines as they come.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F01%2F27%2Fcomet-with-ramaze%2F&amp;linkname=Comet%20with%20Ramaze"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/01/27/comet-with-ramaze/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ramaze 2009.01 released</title>
		<link>http://blog.purepistos.net/index.php/2009/01/12/ramaze-200901-released/</link>
		<comments>http://blog.purepistos.net/index.php/2009/01/12/ramaze-200901-released/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 04:05:01 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=141</guid>
		<description><![CDATA[The Ramaze development team is happy to announce version 2009.01 of Ramaze, the &#8220;unRails&#8221; web development framework for Ruby.  This is our first official release since autumn 2008, which saw quiet releases of 2008.09, .10, .11 and .12.  There have been several fixes and adjustments which have made the overall Ramaze experience smoother. [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>The Ramaze development team is happy to announce version 2009.01 of Ramaze, the &#8220;unRails&#8221; web development framework for Ruby.  This is our first official release since autumn 2008, which saw quiet releases of 2008.09, .10, .11 and .12.  There have been several fixes and adjustments which have made the overall Ramaze experience smoother.  Here&#8217;s a rundown of what changed since 2008.10:</p>

<ul>
<li>The project generator (<code>ramaze --create</code>) should now work under Windows</li>
<li>Most extensions to Ruby core classes have been moved into the Ramaze namespace</li>
<li>String#/ and Symbol#/ have been deprecated (use File.join instead)</li>
<li>Fixed bug which mapped &#8216;/&#8217; to Controller</li>
<li>Changes and improvements to file watching (automatic source reload); will use inotify if available on system</li>
<li>Fixed routing bug which caused occasional, rare routing failures under concurrent load</li>
<li>Fixes, improvements and/or more documentation for the paginate, httpdigest, user, redirect, gravatar, mock_http, markaby helpers</li>
<li>Bench(mark) helper added</li>
<li>Several other minor updates to the core, core warnings and error messages, core docs, and core specs.</li>
<li>Some updates to contrib code</li>
</ul>

<p>Contributions to this release came from many people (listed alphabetically):</p>

<ul>
<li>Aki Reijonen</li>
<li>Aman Gupta (tmm1)</li>
<li>Andreas Karlsson</li>
<li>Andrew Farmer (Xichekolas)</li>
<li>Antti Tuomi (hrnt)</li>
<li>Clive Crous</li>
<li>Colin Shea</li>
<li>Gavin Kistner</li>
<li>Michael Fellinger (manveru)</li>
<li>(Pistos)</li>
<li>Riku Raisaenen (rikur)</li>
<li>Vincent Roy</li>
</ul>

<p>Install or update Ramaze with</p>

<pre><code>gem install ramaze
</code></pre>

<p>It may also be worth mentioning that the Camping dependency that was inadvertently introduced with Rack 0.9.0 is no longer present in Rack 0.9.1, so the latest Rack gem (as of this writing) should be compatible with all recent Ramaze releases.</p>

<p>In addition to announcing this release, I should also mention that a team is currently working on the main website and wiki.  This includes major visual redesign, as well as plenty of content updates.  I&#8217;m hesitant to directly link to the website at this time, as I feel it isn&#8217;t ready for general amazement, but stay tuned!  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>

<p>As usual, we&#8217;d love to hear from long-time users and newbies alike.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Stop by and say hello in <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">our IRC channel</a> (#ramaze on Freenode), or ask questions on <a href="http://groups.google.com/group/ramaze">our mailing list</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2009%2F01%2F12%2Framaze-200901-released%2F&amp;linkname=Ramaze%202009.01%20released"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2009/01/12/ramaze-200901-released/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Conclusion</title>
		<link>http://blog.purepistos.net/index.php/2008/11/26/ramaze-by-example-conclusion/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/26/ramaze-by-example-conclusion/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 20:18:51 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[channel]]></category>
		<category><![CDATA[chat]]></category>
		<category><![CDATA[conclusion]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[irc]]></category>
		<category><![CDATA[learn]]></category>
		<category><![CDATA[learning]]></category>
		<category><![CDATA[list]]></category>
		<category><![CDATA[mailing]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=139</guid>
		<description><![CDATA[This is the conclusion of Ramaze by Example, a tutorial on web development.  In Part 11: Validation and Error Handling, we added a custom error page and handlers for common user errors.

Having gone through this tutorial, you should now know about:


installing Ramaze
setting up a database schema
creating a base Ruby file for an application

models and [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is the conclusion of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/25/ramaze-by-example-part-11-validation-and-error-handling/">Part 11: Validation and Error Handling</a>, we added a custom error page and handlers for common user errors.</em></p>

<p>Having gone through this tutorial, you should now know about:</p>

<ol>
<li>installing Ramaze</li>
<li>setting up a database schema</li>
<li>creating a base Ruby file for an application
<span id="more-139"></span></li>
<li>models and using them to interface with the database</li>
<li>views</li>
<li>interpolating data into views</li>
<li>controllers</li>
<li>the relationship between requests, controller methods and views</li>
<li>how to implement basic <a href="http://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> operations</li>
<li>handling HTTP POSTed data</li>
<li>using layouts for consistent page appearance</li>
<li>where Ramaze gets static files from</li>
<li>basic built-in Ramaze methods and helpers, like the link, flash and redirect helpers</li>
<li>handling errors and displaying error messages</li>
</ol>

<p>Armed with this information, you should be well-equipped to build a small web application of your own right now.</p>

<h3>Learning More</h3>

<p>This tutorial has covered a fair bit, but there are actually considerably more features and functions of Ramaze that I didn&#8217;t discuss.  Some of these are:</p>

<ul>
<li>partials or elements</li>
<li>session variables</li>
<li>aspects</li>
<li>testing</li>
<li>routing</li>
<li>deployment</li>
<li>form helpers and scaffolding generators</li>
<li>cooperation with Javascript, AJAX</li>
<li>&#8230; and more!</li>
</ul>

<p>I hope to cover some of these things in future blog posts.  You can <a href="http://blog.purepistos.net/index.php/feed/">subscribe to my blog via RSS</a> or <a href="http://blog.purepistos.net/index.php/subscribe/">by email</a>.</p>

<p>Here are some resources you can reference to learn more about Ramaze:</p>

<ul>
<li><a href="http://ramaze.net">ramaze.net</a>, the official website</li>
<li><a href="http://rubyconf2008.confreaks.com/ramaze-the-underrated-web-framework.html">The RubyConf 2008 Ramaze presentation</a> by Luc Castera</li>
<li><a href="http://ramaze.net/tutorials:todolist">The original todolist tutorial</a> by manveru</li>
<li><a href="http://github.com/manveru/ramaze/tree/master">The Ramaze codebase</a> &#8211; no really, you can learn a lot from it, and the code is easy to read, and very well commented</li>
<li>The <a href="http://github.com/manveru/ramaze/tree/master/examples">examples/ dir</a> of the Ramaze codebase</li>
<li><a href="http://github.com/manveru/ramaze-book/tree/master">ramaze-book</a>, a partially complete e-book written by manveru</li>
<li>The codebase of <a href="http://github.com/manveru/sociar/tree/master">sociar</a>, an open source social networking platform.  Sociar is pretty much the de facto, comprehensive Ramaze example, written by manveru himself.</li>
<li>The <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">#ramaze IRC channel</a> and <a href="http://groups.google.com/group/ramaze">mailing list</a></li>
</ul>

<h3>Get Started!</h3>

<pre><code># gem install ramaze
</code></pre>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ramaze'</span>
<span style="color:#9966CC; font-weight:bold;">class</span> MainController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Ramaze::Controller</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> index
    <span style="color:#996600;">&quot;Hello, world!&quot;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
Ramaze.<span style="color:#9900CC;">start</span></pre></div></div>


<p>What are you waiting for?  Write your first single-file web application right now!  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   Then stop by our <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">IRC channel</a> and say hello.  We&#8217;d love to hear from you.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F26%2Framaze-by-example-conclusion%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Conclusion"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/26/ramaze-by-example-conclusion/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 11: Validation and Error Handling</title>
		<link>http://blog.purepistos.net/index.php/2008/11/25/ramaze-by-example-part-11-validation-and-error-handling/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/25/ramaze-by-example-part-11-validation-and-error-handling/#comments</comments>
		<pubDate>Wed, 26 Nov 2008 03:52:05 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[custom]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[handling]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[validation]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=138</guid>
		<description><![CDATA[This is part 11 of Ramaze by Example, a tutorial on web development.  In Part 10: Cosmetics, I improved the look of our application.

Up to this point, we&#8217;ve been assuming users will always behave nicely and in predictable ways.  As we all know, this is not a safe assumption in practice, so now [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 11 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/24/ramaze-by-example-part-10-cosmetics/">Part 10: Cosmetics</a>, I improved the look of our application.</em></p>

<p>Up to this point, we&#8217;ve been assuming users will always behave nicely and in predictable ways.  As we all know, this is not a safe assumption in practice, so now we&#8217;ll add some validation and error handling to our application.  I&#8217;ll introduce the changes I made somewhat in reverse order, beginning with error message display.  <span id="more-138"></span></p>

<h4>The Flash Helper</h4>

<p><a href="http://github.com/manveru/ramaze/tree/4909f0185f71eecbc91ce6ae20d41a6bc9c891a6/lib/ramaze/helper/flash.rb" target="github">Ramaze::Helper::Flash</a> is useful for displaying one-time messages to users.  In your controller, you treat <code>flash</code> as a Hash in which you store Strings (usually).  These strings can then be interpolated in views, but not just in handling the current request, but also the <em>next</em> one.  To understand this tool and technique better, let&#8217;s examine how I make use of it in our todo list application.  I&#8217;ve added a <code>fail</code> method to the controller:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#CC0066; font-weight:bold;">fail</span><span style="color:#006600; font-weight:bold;">&#40;</span> message <span style="color:#006600; font-weight:bold;">&#41;</span>
  flash<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:error</span> <span style="color:#006600; font-weight:bold;">&#93;</span> = message
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>It simply takes an argument and assigns it to the <code>:error</code> key of the flash Hash.  I call the <code>fail</code> method whenever I want to send an error message to the user.  To actually display the message, we use the method <code>flashbox</code> in our layout:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;h1<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>#{@title}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/h1<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  #{flashbox}
  #{@content}
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<h4>Checking the operand</h4>

<p>Our check off and delete actions have been assuming that there always exists a task that has an id matching the id parameter given.  Now we&#8217;re going to check whether this is true, and handle the situation gracefully if the condition false.</p>

<p>Since we&#8217;re going to perform this check in more than one spot, we stay <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> by making a single method to do the check, a method we will call from multiple places.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> ensure_task_exists<span style="color:#006600; font-weight:bold;">&#40;</span> id <span style="color:#006600; font-weight:bold;">&#41;</span>
  task = Task<span style="color:#006600; font-weight:bold;">&#91;</span> id <span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">if</span> task.<span style="color:#0000FF; font-weight:bold;">nil</span>?
    <span style="color:#CC0066; font-weight:bold;">fail</span> <span style="color:#996600;">&quot;No task with id #{id}.&quot;</span>
    redirect_referrer
  <span style="color:#9966CC; font-weight:bold;">end</span>
  task
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>If there is no task in the database with the given id, then we call our <code>fail</code> method to setup an error message, and then redirect the user back to wherever she came from with <code>redirect_referrer</code>.  If instead the task exists, we simply return the task to the method caller.</p>

<p>So next, we change the action methods to make use of this utility method.  Here&#8217;s a diff of the relevant part of the controller:</p>


<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">   def check_off<span style="">&#40;</span> id <span style="">&#41;</span>
<span style="color: #991111;">-    Task<span style="">&#91;</span> id <span style="">&#93;</span>.check_off</span>
<span style="color: #00b000;">+    task = ensure_task_exists<span style="">&#40;</span> id <span style="">&#41;</span></span>
<span style="color: #00b000;">+    task.check_off</span>
     redirect Rs<span style="">&#40;</span> :/ <span style="">&#41;</span>
   end
&nbsp;
   def delete<span style="">&#40;</span> id <span style="">&#41;</span>
<span style="color: #991111;">-    Task<span style="">&#91;</span> id <span style="">&#93;</span>.delete</span>
<span style="color: #00b000;">+    task = ensure_task_exists<span style="">&#40;</span> id <span style="">&#41;</span></span>
<span style="color: #00b000;">+    task.delete</span>
     redirect Rs<span style="">&#40;</span> :/ <span style="">&#41;</span>
   end</pre></div></div>


<p>Observe how the error handling and redirection are nicely parcelled away elsewhere, keeping the action code clean and succinct.</p>

<h4>Seeing errors in action</h4>

<p>Now, run the code:</p>

<pre><code>  git checkout 11-error-handling
  ruby start.rb
</code></pre>

<p>and visit <a href="http://localhost:9000/delete/99999" target="tutorial">/delete/99999</a> to see this error handling code work.  The important thing to notice here is that even though the error message is set in one action (<code>delete</code>), it is available for usage in the next requested action (<code>index</code>).  However, it will not be available to future requests (unless it is set again).  That&#8217;s why it&#8217;s called the &#8220;flash&#8221; hash: because data only remains for a short while.</p>

<h4>Constraining the input</h4>

<p>We would like to ensure that task descriptions are not empty.  While other developers may choose to constrain data at the model or view (Javascript) level, I&#8217;m of the persuasion that one should constrain data as much as possible at the database level, to maximize one&#8217;s confidence that the data in the database is as pristine as possible.  So I will setup the constraint in the schema:</p>


<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER</span> <span style="color: #993333; font-weight: bold;">TABLE</span> tasks
  <span style="color: #993333; font-weight: bold;">ADD</span> CONSTRAINT minimum_description_length
  <span style="color: #993333; font-weight: bold;">CHECK</span> <span style="color: #66cc66;">&#40;</span> char_length<span style="color: #66cc66;">&#40;</span> description <span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">&#41;</span>;</pre></div></div>


<p>After adding this constraint, if you try to enter a description which is less than 2 characters long, it will fail &#8212; but not very gracefully.  So we add some grace by rewriting our <code>create</code> method:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> create
  description = h<span style="color:#006600; font-weight:bold;">&#40;</span> request<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">'description'</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">strip</span>
  <span style="color:#9966CC; font-weight:bold;">begin</span>
    Task.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:description</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> description <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#6666ff; font-weight:bold;">DBI::ProgrammingError</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> e
    <span style="color:#9966CC; font-weight:bold;">if</span> e.<span style="color:#9900CC;">message</span> =~ <span style="color:#006600; font-weight:bold;">/</span>minimum_description_length<span style="color:#006600; font-weight:bold;">/</span>
      <span style="color:#CC0066; font-weight:bold;">fail</span> <span style="color:#996600;">'Please enter an adequate description for the new task.'</span>
      redirect Rs<span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:new</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#CC0066; font-weight:bold;">raise</span> e
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
  redirect Rs<span style="color:#006600; font-weight:bold;">&#40;</span> :<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>As you can see, we are wrapping the <code>Task.create</code> call with a begin/rescue pair so we can handle the exception thrown by the database.  The <code>if</code> block inside the rescue clause is used to handle a specific exception, namely a violation of the <code>minimum_description_length</code> constraint which we named and defined earlier.  If an exception of this kind is thrown, then we setup an error message with <code>fail</code> and <code>redirect</code> back to the task addition page.  If it&#8217;s some other kind of exception, we don&#8217;t want to swallow it up; instead we re-<code>raise</code> it.  If no exception is raised, then the user is redirected to the task list.</p>

<p><a href="http://localhost:9000/new" target="tutorial">Try this out</a> to see for yourself that it works.  (Don&#8217;t forget to add the constraint first if you haven&#8217;t done so already.)</p>

<h4>Custom error handler</h4>

<p>Up to this point, we&#8217;ve worked with errors which we anticipate and handle.  In reality, we can never foresee every possible error.  If you check out the previous tutorial part&#8217;s code and run it (<code>git checkout 10-cosmetics; ruby start.rb</code>), then try to visit a non-existent page, such as <a href="http://localhost:9001/foobar" target="tutorial">http://localhost:9001/foobar</a>, you will see an error message and stack trace, something like this:</p>

<pre style="overflow: auto;">
No Action found for `/foobar' on MainController
  /usr/lib/ruby/site_ruby/1.8/ramaze/lib/ramaze/controller/resolve.rb:274:in `raise_no_action'
  /usr/lib/ruby/site_ruby/1.8/ramaze/lib/ramaze/controller/resolve.rb:98:in `default'
  /usr/lib/ruby/site_ruby/1.8/ramaze/lib/ramaze/controller/resolve.rb:25:in `send'
...
</pre>

<p>Ramaze lets you override this error page with one of your own; simply put something in place to handle an <code>error</code> action.  As we&#8217;ve learned, that means either a controller method, or a view, or both.  Here&#8217;s the controller method we add:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> error
  <span style="color:#0066ff; font-weight:bold;">@title</span> = <span style="color:#996600;">'Application Error'</span>
  <span style="color:#0066ff; font-weight:bold;">@e</span> = <span style="color:#6666ff; font-weight:bold;">Ramaze::Dispatcher::Error</span>.<span style="color:#9900CC;">current</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Whenever an exception occurs in a Ramaze application, the <code>error</code> action is hit.  If no handler is set up by the application programmer, Ramaze will use a default <code>error</code> method.</p>

<p><code>Ramaze::Dispatcher::Error.current</code> evaluates to the Ruby Exception which has been raised and is causing the error condition.  We make it available to our view so we can display information about the exception.  Here is our <code>error.xhtml</code> view to go with the <code>error</code> method:</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h2</span>&gt;</span>#{@e.message}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h2</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
  <span style="color: #009900;">&lt;?r @e.backtrace.each do |frame| ?&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;</span>#{frame}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
  <span style="color: #009900;">&lt;?r end ?&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span></pre></div></div>


<p>It should be relatively clear what the above combination of method and view does, but in case it isn&#8217;t for you, <code>git checkout 11-error-handling; ruby start.rb</code> and visit <a href="http://localhost:9001/foobar" target="tutorial">http://localhost:9001/foobar</a> again.</p>

<h3>Review</h3>

<p>Let&#8217;s review what we&#8217;ve learned over the final parts of this tutorial:</p>

<ul>
<li>Layouts are used to keep view code dry and maintain a consistent look across multiple views.</li>
<li>A layout is just another view, one which interpolates <code>#{@content}</code>.</li>
<li><code>@content</code> contains the rendering of a view (or, in other words, a layout &#8220;wraps&#8221; other views).</li>
<li>The <code>layout</code> method is used in a controller definition to tell Ramaze which view to use as the layout view for a controller.  It accepts a Hash argument, with the key-value pair being the site path of the layout view, and an array of controller methods (actions) to apply the layout to.  e.g.<br/><code>layout '/page' => [ :index, :new ]</code></li>
<li>Layouts can make use of controller instance variables (e.g. <code>@title</code>) just like normal views.</li>
<li>Static files (CSS, Javascript, images, etc.) are placed in a <code>public/</code> subdirectory in your application&#8217;s file tree.</li>
<li><code>flash</code> is a session-wide Hash.</li>
<li>Data stored in the <code>flash</code> Hash persists only for two requests, making it useful for temporarily storing messages for the user across redirects.</li>
<li><code>flashbox</code> is used in views, and evaluates to an HTML <code>&lt;div&gt;</code> for each key-value pair in the <code>flash</code> Hash.</li>
<li><code>redirect_referrer</code> is used to redirect a browser back to the referring page.</li>
</ul>

<p>In the <a href="http://blog.purepistos.net/index.php/2008/11/26/ramaze-by-example-conclusion/">Conclusion</a>, I will wrap up the tutorial and talk about further avenues of exploration and learning.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F25%2Framaze-by-example-part-11-validation-and-error-handling%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%2011%3A%20Validation%20and%20Error%20Handling"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/25/ramaze-by-example-part-11-validation-and-error-handling/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 10: Cosmetics</title>
		<link>http://blog.purepistos.net/index.php/2008/11/24/ramaze-by-example-part-10-cosmetics/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/24/ramaze-by-example-part-10-cosmetics/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 14:29:31 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[cosmetics]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[public]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=137</guid>
		<description><![CDATA[This is part 10 of Ramaze by Example, a tutorial on web development.  In Part 9: Layout, I demonstrated how to use layouts for a consistent frontend look.

In this part, I change several things in the view layer so that the site looks a bit better.  The exact details of the HTML changes [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 10 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/23/ramaze-by-example-part-9-layout/">Part 9: Layout</a>, I demonstrated how to use layouts for a consistent frontend look.</em></p>

<p>In this part, I change several things in the view layer so that the site looks a bit better.  The exact details of the HTML changes are not pertinent to learning Ramaze, so I won&#8217;t go over them.  You can view them yourself by doing the usual branch diff.</p>

<p>In this part of the tutorial, I introduce a CSS file.  The reference in <code>layout.xhtml</code> is typical for web development in general: <span id="more-137"></span></p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">link</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/layout.css&quot;</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span></span>
<span style="color: #009900;">  <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>


<p>But where exactly should one put one&#8217;s CSS files?  Ramaze, by default, serves static files from a subdirectory called <code>public/</code>.  This is where I&#8217;ve put <code>layout.css</code>.  You would put other static resources under <code>public</code> as well; things such as Javascript files, images, video files, and so on.  The paths you write in your HTML should correspond to the path relative to the <code>public/</code> directory.  For example, a reference like</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">img</span> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/images/banner.png&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span></pre></div></div>


<p>would make Ramaze serve a <code>public/images/banner.png</code> file.</p>

<p>Next, in <a href="http://blog.purepistos.net/index.php/2008/11/25/ramaze-by-example-part-11-validation-and-error-handling/">Part 11: Validation and Error Handling</a>, we&#8217;ll see how to gracefully deal with unusual user behaviour.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F24%2Framaze-by-example-part-10-cosmetics%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%2010%3A%20Cosmetics"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/24/ramaze-by-example-part-10-cosmetics/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 9: Layout</title>
		<link>http://blog.purepistos.net/index.php/2008/11/23/ramaze-by-example-part-9-layout/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/23/ramaze-by-example-part-9-layout/#comments</comments>
		<pubDate>Sun, 23 Nov 2008 15:09:15 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[layout]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[templating]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=136</guid>
		<description><![CDATA[This is part 9 of Ramaze by Example, a tutorial on web development.  In Part 8: Deleting Tasks, we added the ability to delete tasks.

If you look at our two views, you might notice that there is some common code in both.  Being good coders, we know that such unnecessary duplication is bad [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 9 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-8-deleting-tasks/">Part 8: Deleting Tasks</a>, we added the ability to delete tasks.</em></p>

<p>If you <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/8-delete-task/view" target="github">look at our two views</a>, you might notice that there is some common code in both.  Being good coders, we know that such unnecessary duplication is bad for maintenance and debugging, and also hinders our flexibility for future changes we might want to make.</p>

<p>Fortunately, Ramaze has some facilities that let you consolidate shared view code.  One of these facilities is the ability to use layouts.  <span id="more-136"></span></p>

<h4>A layout template</h4>

<p>In the 9-layout git branch, I add a <code>layout.xhtml</code> view file:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>#{@title}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/title<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/head<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;h1<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>#{@title}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/h1<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    #{@content}
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/body<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/html<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<p>I&#8217;ve copied roughly the top and bottom parts of both existing views.  The differences are that I&#8217;m interpolating the title, and that the middle portion of each view is not present.  Instead, there is another interpolation: <code style="white-space: nowrap">#{@content}</code>.  I&#8217;ll hold off explaining this&#8230;</p>

<h4>Adjusting the controller</h4>

<p>We now have a layout view, but to make use of it, we need to make some changes to our controller.  Looking at the source code diff, you can see that in <code>MainController</code> I&#8217;m using a <code>Ramaze::Controller</code> class method, <a href="http://github.com/manveru/ramaze/tree/a6c24f7d7b767fc9579749a1a8b299c1d0c78a19/lib/ramaze/controller.rb#L112" target="github"><code>layout</code></a>:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">layout <span style="color:#996600;">'/layout'</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#ff3333; font-weight:bold;">:index</span>, <span style="color:#ff3333; font-weight:bold;">:new</span> <span style="color:#006600; font-weight:bold;">&#93;</span></pre></div></div>


<p>The layout method takes a Hash argument.  The hash key is the path to the layout.  This path is specified from the root of the site (a common newbie mistake is to specify the filesystem path).  The hash value is an array of symbols corresponding to the paths that we want laid out by the layout.  If we omitted the array, the layout would apply to all paths, but most applications would not want this behaviour.  For example, remember that our application has controller methods that handle creation and deletion of tasks.  In general, it&#8217;s better to be explicit about what pages you want laid out.</p>

<p>I further adjust the controller by specifying each page&#8217;s <code>@title</code>, to be picked up by the layout.</p>

<h4>Modifying the views</h4>

<p>Since we are trying to move duplicate code into a single, shared location, we should remove that code from their original places in the views.  To see exactly what I&#8217;ve removed, view <code>git diff 8-delete-task 9-layout</code>.</p>

<p>Now the only thing left in the views are the inner portions that distinguish them from one another.  For example, here&#8217;s what&#8217;s left of <code>view/new.xhtml</code>:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;a</span> <span style="color: #000066;">href</span>=<span style="color: #ff0000;">&quot;/&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>Back to task list<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/a<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;form</span> <span style="color: #000066;">method</span>=<span style="color: #ff0000;">&quot;POST&quot;</span> <span style="color: #000066;">action</span>=<span style="color: #ff0000;">&quot;create&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  Description: <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;description&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span><span style="color: #000000; font-weight: bold;">&lt;br</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;submit&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/form<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>


<h4>See the layout in action</h4>

<p>So, check out the 9-layout branch, and take a look at the result of the changes.</p>

<pre><code>git checkout 9-layout
ruby start
</code></pre>

<p><a href="http://localhost:9001" target="tutorial">http://localhost:9001</a></p>

<p>Use View Source in your browser to see for yourself that a full webpage is rendered, even though neither the layout alone, nor the view alone has a complete page of HTML.  Observe also that the <code>@title</code> we set in different controller methods passes along to the layout as well.</p>

<p>We&#8217;ll pretty up the face of our application a bit in <a href="http://blog.purepistos.net/index.php/2008/11/24/ramaze-by-example-part-10-cosmetics/">Part 10: Cosmetics</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F23%2Framaze-by-example-part-9-layout%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%209%3A%20Layout"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/23/ramaze-by-example-part-9-layout/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 8: Deleting Tasks</title>
		<link>http://blog.purepistos.net/index.php/2008/11/22/ramaze-by-example-part-8-deleting-tasks/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/22/ramaze-by-example-part-8-deleting-tasks/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 14:53:11 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[m4dbi]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[redirect]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=135</guid>
		<description><![CDATA[This is part 8 of Ramaze by Example, a tutorial on web development.  In Part 7: Checking off Tasks, we added to our application the ability to check off completed tasks.

We&#8217;ll round out the functionality of our app by adding a way to delete tasks from the list.  As is commonplace when building [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 8 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/21/ramaze-by-example-part-7-checking-off-tasks/">Part 7: Checking off Tasks</a>, we added to our application the ability to check off completed tasks.</em></p>

<p>We&#8217;ll round out the functionality of our app by adding a way to delete tasks from the list.  As is commonplace when building a feature into an app, we think about implementation in terms of changes to the three parts of MVC.  In this case, we don&#8217;t need to make any changes to the model, because M4DBI provides us with deletion functionality for free.</p>

<h4>Modifying the view</h4>

<p><a href="http://github.com/Pistos/ramaze-todolist-tutorial/commit/61213b074e79bb6152905164e466e52ca5f11b21#L1R15" target="github">In the list view, we add a link</a> for users to click on to delete tasks:  <span id="more-135"></span></p>

<pre>
(#{ A( 'delete', :href => Rs( :delete, task.id_ ) ) })
</pre>

<p>Nothing new here.  I&#8217;m using <code>A</code> and <code>Rs</code> to build a link to a &#8216;/delete&#8217; path, passing a task id as a parameter.</p>

<h4>Modifying the controller</h4>

<p>And of course, we need something to receive &#8216;/delete&#8217; requests, so we add this to our controller:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> delete<span style="color:#006600; font-weight:bold;">&#40;</span> id <span style="color:#006600; font-weight:bold;">&#41;</span>
  Task<span style="color:#006600; font-weight:bold;">&#91;</span> id <span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">delete</span>
  redirect Rs<span style="color:#006600; font-weight:bold;">&#40;</span> :<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>This should look straightforward, too.  The <code>delete</code> method of <code>MainController</code> will be executed on requests for &#8216;/delete&#8217;, and it will take the id number passed as a parameter.</p>

<p>So we grab the task from the database using our <code>Task</code> model, then call the <code>delete</code> method on the task instance.  When we&#8217;re done, we <code>redirect</code> back to the list, so there is no need for a <code>delete.xhtml</code> view.</p>

<p>Wasn&#8217;t that easy?  Check out what we just did:</p>

<pre><code>git checkout 8-delete-task
ruby start.rb
</code></pre>

<p>and surf to <a href="http://localhost:9001">http://localhost:9001</a>.</p>

<h3>Review</h3>

<p>Let&#8217;s review what we&#8217;ve learned while fleshing out the functionality of our application.</p>

<ul>
<li>Ramaze can respond to requests when only a controller method or only a view is present (it doesn&#8217;t require both).</li>
<li>Controller methods should match controller paths.  e.g. <code>def create</code> matches &#8216;/create&#8217;.</li>
<li>The <code>request</code> object acts like a Hash to provide access to POSTed parameters, keyed by field name.</li>
<li><a href="http://github.com/manveru/ramaze/tree/4a4da0bcd059e5275c4fece05fb2348b41cb941d/lib%2Framaze%2Fhelper%2Fcgi.rb#L31" target="github"><code>h()</code></a> is used to sanitize (escape) potentially malicious strings.</li>
<li><a href="http://github.com/manveru/ramaze/tree/4a4da0bcd059e5275c4fece05fb2348b41cb941d/lib%2Framaze%2Fhelper%2Fredirect.rb#L44" target="github"><code>redirect</code></a> is used to redirect to another site path.</li>
<li><a href="http://github.com/manveru/ramaze/tree/6d4353f5421c23c6126bfb4da2392cf457b6f82f/lib/ramaze/helper/link.rb#L26" target="github"><code>A()</code></a> is used to generate HTML <code>&lt;a&gt;</code> tags.</li>
<li><a href="http://github.com/manveru/ramaze/tree/6d4353f5421c23c6126bfb4da2392cf457b6f82f/lib/ramaze/helper/link.rb#L82" target="github"><code>R()</code></a> and <a href="http://github.com/manveru/ramaze/tree/6d4353f5421c23c6126bfb4da2392cf457b6f82f/lib/ramaze/helper/link.rb#L82" target="github"><code>Rs()</code></a> are used to build site path strings relative to a controller&#8217;s mapped root.  We can use these paths with <code>h</code>, <code>A</code>, <code>redirect</code> and anything else that needs a path string.</li>
<li>Controller methods can take arguments; these arguments correspond to a slash-separated list of parameters in a request.<br/>e.g. <code>def check_off( id )</code> corresponds to a request like &#8216;/check_off/32&#8242;.</li>
<li>M4DBI model classes are extensible.</li>
</ul>

<p>In <a href="http://blog.purepistos.net/index.php/2008/11/23/ramaze-by-example-part-9-layout/">Part 9: Layout</a>, I will introduce a <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a> way to have a consistent look across multiple web pages.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F22%2Framaze-by-example-part-8-deleting-tasks%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%208%3A%20Deleting%20Tasks"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/22/ramaze-by-example-part-8-deleting-tasks/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 7: Checking off Tasks</title>
		<link>http://blog.purepistos.net/index.php/2008/11/21/ramaze-by-example-part-7-checking-off-tasks/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/21/ramaze-by-example-part-7-checking-off-tasks/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 16:30:41 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[m4dbi]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[view]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=134</guid>
		<description><![CDATA[This is part 7 of Ramaze by Example, a tutorial on web development.  In Part 6: Adding Tasks, we added the ability create new tasks to our application.

So now we are able to record things that need to be done; but we have no way of marking them completed!

Modifying the view

Examining the source code [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 7 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-6-adding-tasks/">Part 6: Adding Tasks</a>, we added the ability create new tasks to our application.</em></p>

<p>So now we are able to record things that need to be done; but we have no way of marking them completed!</p>

<h4>Modifying the view</h4>

<p>Examining the source code delta (<code>git checkout 7-check-off-task; git diff 6-add-task</code>), you&#8217;ll see that I added this to our <code>index.xhtml</code> view:</p>


<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?r</span> if not task.done <span style="color: #000000; font-weight: bold;">?&gt;</span></span>
  [#{ A(
    '<span style="color: #ddbb00;">&amp;nbsp;&amp;nbsp;</span>',
    :href =&gt; Rs( :check_off, task.id_ )
  ) }]
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?r</span> end <span style="color: #000000; font-weight: bold;">?&gt;</span></span></pre></div></div>


<p>It looks a bit convoluted, but let me explain each little bit.  <span id="more-134"></span></p>

<p>I used <code>&lt;?r ?&gt;</code> to use a condition.  If the task is not done yet, then we&#8217;d like to display a checkbox for users to check off the task.  If the task is done, then we <em>don&#8217;t</em> want to show a checkbox.  Note the matching <code>end</code> at the bottom; this makes the stuff in between <code>if</code> and <code>end</code> render only when the condition is true, as you would expect from normal Ruby code.</p>

<p>I&#8217;m using square brackets to &#8220;draw&#8221; a checkbox ( &#8220;[ ]&#8221; ).  Following the opening bracket, we have <code>#{</code>, which opens up string interpolation, as per normal Ruby.  Inside the interpolation, I am making a call to a built-in Ramaze method, <code>A()</code>.  Like <code>R</code> and <code>Rs</code>, <a href="http://github.com/manveru/ramaze/tree/6d4353f5421c23c6126bfb4da2392cf457b6f82f/lib/ramaze/helper/link.rb#L26" target="github"><code>A</code> is part of Ramaze&#8217;s LinkHelper</a>.  You use it to build links (HTML <code>&lt;a&gt;</code> tags).  The first argument I pass to <code>A</code> is the clickable text to be displayed (the content of the <code>&lt;a&gt;</code> tag).  The second argument is an attribute hash, in this case consisting simply of the href attribute for the <code>&lt;a&gt;</code> tag.</p>

<p>I use <code>Rs</code> to build the href, passing <code>Rs</code> the path and then an argument.  If you run the code of step 7 (<code>ruby start.rb</code>), and browse to the site and view source, you&#8217;ll see the <code>&lt;a&gt;</code> tags that were built, including the parameters on the hrefs.  Each link points to a &#8216;/check_off&#8217; path, passing the task&#8217;s id number as a parameter.  (I use <code>id_</code> instead of <code>id</code> because <code>id</code> is reserved in Ruby 1.8.  M4DBI knows that you mean <code>id</code> when you use <code>id_</code>.)</p>

<h4>Modifying the controller</h4>

<p>Next, we add a method to the controller to handle the browser requests that will come when users click on checkboxes.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> check_off<span style="color:#006600; font-weight:bold;">&#40;</span> id <span style="color:#006600; font-weight:bold;">&#41;</span>
  Task<span style="color:#006600; font-weight:bold;">&#91;</span> id <span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">check_off</span>
  redirect Rs<span style="color:#006600; font-weight:bold;">&#40;</span> :<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>As you might expect, I match the name of the method with the path in the links.  Also, the method accepts a parameter, just like the links have a parameter on them (e.g. &#8216;/check_off/5&#8242; ).  Nice and intuitive.</p>

<p>In the method, using our model, we pull out of the database the task with the corresponding id number: <code>Task[ id ]</code>.  Then we execute the <code>check_off</code> method on that task.</p>

<p>And when we&#8217;re done, we <code>redirect</code> back to the todo list.</p>

<h4>Modifying the model</h4>

<p>Those of you paying attention may have asked: &#8220;check_off method?  What check_off method?&#8221;  Your suspicion is warranted: there is no <code>check_off</code> method &#8212; yet.  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   To complete our work in this phase of the tutorial, we extend our model as follows:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> check_off
  <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">done</span> = <span style="color:#0000FF; font-weight:bold;">true</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Although M4DBI automatically gives us read and write access to table rows via column names, sometimes we want to have more than just that basic level of functionality.  You can extend a model class by adding more methods.  In this case, we&#8217;ve added a method to mark a task done.  Although making a method out of a simple one-liner is not strictly necessary in this case (we could have put <code>Task[ id ].done = true</code> directly in the controller method), this is slightly better design (discussion and debate of this are left as exercises for the readers <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  ).</p>

<h4>Try it!</h4>

<p>And that&#8217;s all we need to do to add the ability to check off tasks!  Try it yourself:</p>

<pre><code>git checkout 7-check-off-task
ruby start.rb
</code></pre>

<p>then browse <a href="http://localhost:9001">http://localhost:9001</a>.</p>

<p>We&#8217;ll round out the functionality of our app in <a href="http://blog.purepistos.net/index.php/2008/11/22/ramaze-by-example-part-8-deleting-tasks/">Part 8: Deleting Tasks</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F21%2Framaze-by-example-part-7-checking-off-tasks%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%207%3A%20Checking%20off%20Tasks"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/21/ramaze-by-example-part-7-checking-off-tasks/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 6: Adding Tasks</title>
		<link>http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-6-adding-tasks/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-6-adding-tasks/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 18:10:11 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[link]]></category>
		<category><![CDATA[POST]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=133</guid>
		<description><![CDATA[This is part 6 of Ramaze by Example, a tutorial on web development.  In Part 5: Controller, we coded some of the core processing of our application.

So now we have a fully functional Ramaze application, with all components of MVC, each elegantly and intuitively working together with one another.  However, our app&#8217;s actual [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 6 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-5-controller">Part 5: Controller</a>, we coded some of the core processing of our application.</em></p>

<p>So now we have a fully functional Ramaze application, with all components of MVC, each elegantly and intuitively working together with one another.  However, our app&#8217;s actual functionality is very limited at the moment, so let&#8217;s build on that.  We&#8217;ll add the ability to add more tasks to our todo list.  <span id="more-133"></span></p>

<h4>A link</h4>

<p>First, we <a href="http://github.com/Pistos/ramaze-todolist-tutorial/commit/03ec20aaeab5b696172039adde75e6950ff5096a#L0R7" target="github">introduce a way to add a task</a> to our interface.  Just a simple link in the <code>index</code> view:</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">a</span> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;/new&quot;</span>&gt;</span>Add Task<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">a</span>&gt;</span></pre></div></div>


<p>If you run the server (<code>ruby start.rb</code>) and visit that address in your browser at this point (those of you following along with git should <code>git checkout 5-controller</code> and visit <a href="http://localhost:9001/new" target="tutorial">http://localhost:9001/new</a>), you will encounter an error page, with a message like:</p>

<blockquote>
  <p>No Action found for `/new&#8217; on MainController</p>
</blockquote>

<p>That&#8217;s because, although we have an <code>index</code> method in <code>MainController</code> and an <code>index.html</code> view to handle requests for &#8216;/&#8217;, we don&#8217;t have anything to handle requests for &#8216;/new&#8217;.  The clever among you might suppose we have to add a <code>new</code> method to <code>MainController</code>.  You could do that; but actually, Ramaze will respond to requests when only a view (or only a method) is present, which is exactly <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/03ec20aaeab5b696172039adde75e6950ff5096a/view/new.xhtml" target="github">what we add</a>.</p>

<h4>An entry form</h4>

<p>As you can see, <code><a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/03ec20aaeab5b696172039adde75e6950ff5096a/view/new.xhtml" target="github">view/new.xhtml</a></code> consists entirely of static HTML; no variable references or Ruby code like we saw in <code><a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/6-add-task/view/index.xhtml" target="github">view/index.xhtml</a></code>.  We won&#8217;t add anything to our controller at this point.</p>

<p>If you surf to <a href="http://localhost:9001" target="tutorial">your tutorial site</a> after adding the <code>new</code> view (<code>git checkout 6-add-task</code>), you&#8217;ll see Ramaze render the HTML.</p>

<p>The new view contains a form which accepts the description for a new task, and then <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/6-add-task/view/new.xhtml#L8" target="github">POSTs to &#8216;create&#8217;</a>.  We don&#8217;t have any code to handle a request for &#8216;/create&#8217;, so let&#8217;s add that next.</p>

<h4>A submission handler</h4>

<p>You can see (<code>git diff 5-controller</code>) that I added a new method to the controller:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">def</span> create
  Task.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span>
    <span style="color:#ff3333; font-weight:bold;">:description</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> h<span style="color:#006600; font-weight:bold;">&#40;</span> request<span style="color:#006600; font-weight:bold;">&#91;</span> <span style="color:#996600;">'description'</span> <span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#006600; font-weight:bold;">&#41;</span>
  redirect Rs<span style="color:#006600; font-weight:bold;">&#40;</span> :<span style="color:#006600; font-weight:bold;">/</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>In this method, we first create a new task in our database via our Task model.  <code>request[ 'description' ]</code> evaluates to what the user typed into <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/6-add-task/view/new.xhtml#L9" target="github">the <code>description</code> field in the entry form</a>.</p>

<p><a href="http://github.com/manveru/ramaze/tree/master/lib/ramaze/helper/cgi.rb#L31" target="github"><code>h()</code></a> is another helper method of Ramaze (part of <a href="http://github.com/manveru/ramaze/tree/master/lib/ramaze/helper/cgi.rb" target="github">Ramaze::Helper::CGI</a>).  It safely escapes HTML and code that could be dangerous when strings are placed into templates.  It&#8217;s good practice to use <code>h</code> to sanitize all user input which could be displayed in a template, since malicious users might try to inject HTML or Ruby code into your views.  Here, we are sanitizing at source, at the point of entry into the database (as opposed to at the point of display, in the view, or the controller method related to data display).</p>

<p>After adding to the database, we <code>redirect</code> the browser back to the task list which resides at the root (/) of the site.  <a href="http://github.com/manveru/ramaze/tree/6d4353f5421c23c6126bfb4da2392cf457b6f82f/lib/ramaze/helper/link.rb#L82" target="github"><code>R</code></a> is a built-in Ramaze method which generates proper paths for use in links.  <a href="http://github.com/manveru/ramaze/tree/6d4353f5421c23c6126bfb4da2392cf457b6f82f/lib/ramaze/helper/link.rb#L82" target="github"><code>Rs</code></a> is a specialized version of <code>R</code> which builds paths based on the current controller.  Think &#8220;R for reference&#8221; as in &#8220;href&#8221;.  We also could have used <code>redirect '/'</code> but using <code>R</code> or <code>Rs</code> helps us stay flexible.  When developing an application, you may choose to map a controller to a different path.</p>

<p>So, after typing in a description and pressing the submit button, a new task is added to the database, and the user is returned to the task list.</p>

<p><a href="http://blog.purepistos.net/index.php/2008/11/21/ramaze-by-example-part-7-checking-off-tasks/">Part 7: Checking off Tasks</a> adds more functionality to our app.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F20%2Framaze-by-example-part-6-adding-tasks%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%206%3A%20Adding%20Tasks"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-6-adding-tasks/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 5: Controller</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-5-controller/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-5-controller/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:43:50 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[controller]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=132</guid>
		<description><![CDATA[This is part 5 of Ramaze by Example, a tutorial on web development.  In Part 4: View, we coded up the front end of our application.

The Controller part of the MVC pattern is the meat of your application.  As much as possible, the logic, thinking, rules, and procesess of your application should be [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 5 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-4-view">Part 4: View</a>, we coded up the front end of our application.</em></p>

<p>The Controller part of the MVC pattern is the meat of your application.  As much as possible, the logic, thinking, rules, and procesess of your application should be placed in controllers.  A controller acts as a hub, or a central place of command.  Controllers interact with models to read the state of the system, prepare variables with data that the views display, accept interactions from the user, and use models to modify the system state stored in the database.  To do things by the book, you should try to keep to a minimum the Ruby code used in your views, and instead place it in controllers.  <span id="more-132"></span></p>

<p>Ramaze has no expectation about where your controller code should go.  A common convention is to place controller source code under a <code>src/</code> subdirectory in your project.  Note that this corresponds with <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/2-base-app/start.rb#L8" target="github">the acquire statement in start.rb</a>.  Here is <code>src/main.rb</code>:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> MainController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Ramaze::Controller</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> index
    <span style="color:#0066ff; font-weight:bold;">@tasks</span> = Task.<span style="color:#9900CC;">all</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>We have just this one controller in our application.  To define a controller, make a subclass of the <code>Ramaze::Controller</code> class.  We call our controller class <code>MainController</code>.  The name <code>MainController</code> is somewhat of a convention in Ramaze.  Later, we&#8217;ll see what bearing this has on Ramaze applications.</p>

<p>In the controller, there is an <code>index</code> method.  In it, we see the initialization of a <code>@tasks</code> variable, the very same <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/4-view/view/index.xhtml#L8" target="github">@tasks variable we reference in our view</a>.  This exemplifies that <em>instance variables in controller methods are used to make data available to views</em>.</p>

<p>The right-hand side of the assignment is <code>Task.all</code>.  What this tiny piece of code is doing is using <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/3-model/src/model/task.rb" target="github">the Task model</a> to retrieve <code>all</code> the tasks from the database.  If you were to <code>inspect</code> the <code>@tasks</code> variable, you would see that the <code>DBI::Model.all</code> method returns an Array of model objects; in this case, tasks.</p>

<h3>MVC in action</h3>

<p>If you&#8217;re new to the MVC pattern, the last three parts of the tutorial may seem like a lot to digest.  It would aid understanding a lot, though, to see these three components work together to deliver a web page.  So let&#8217;s see the fruit of the effort we&#8217;ve spent up to this point.  If you&#8217;ve got the tutorial source code cloned, switch to the branch for part 5:</p>

<pre><code>git checkout 5-controller
</code></pre>

<p>Now let&#8217;s start up our Ramaze application.  Do this by running <code>start.rb</code>:</p>

<pre><code>ruby start.rb
</code></pre>

<p>After a moment of initialization, you should see output similar to this:</p>

<pre style="overflow: auto">
[2008-11-12 22:50:09] INFO   Starting up Ramaze (Version 2008.10)
[2008-11-12 22:50:09] WARN   Public root: 'public' doesn't exist
[2008-11-12 22:50:09] DEBUG  mapped Controllers: {"/"=>MainController}
[2008-11-12 22:50:09] INFO   Ramaze is ready to run on: 0.0.0.0:9001 using Ramaze::Adapter::Mongrel
</pre>

<p>Now browse to <a href="http://localhost:9001" target="app">http://localhost:9001</a>.  You should see a simple page consisting of a title and a list of tasks.  There are several things we can observe:</p>

<ol>
<li>The HTML source code of this page came from our view, <code><a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/4-view/view/index.xhtml" target="github">view/index.xhtml</a></code>.  (Use Ctrl-U in most browsers to view the HTML source of the page.)</li>
<li>The static parts of the template are served as-is by Ramaze to the browser.</li>
<li>The dynamic parts are processed by Ramaze, and the <em>results</em> of the processing are placed in the template.</li>
<li>Browsing the <em>root</em> of a Ramaze website causes Ramaze to execute the <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/5-controller/src/main.rb#L2" target="github"><code><em>index</em></code> method</a> of <code>MainController</code>, and <em>render</em> the <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/4-view/view/index.xhtml" target="github"><code><em>index</em></code> view</a>.  In MVC terms, we say that &#8220;the path &#8216;/&#8217; is <em>mapped</em> to MainController&#8221;.</li>
</ol>

<p>This mapping is actually just a default; it is possible to map the root path to a different controller, or to map MainController to a different path.</p>

<p>If you look at the log output of Ramaze, you&#8217;ll see a line like this:</p>

<pre style="overflow: auto">
[2008-11-13 23:35:52] INFO   Dynamic request from 127.0.0.1: /
</pre>

<p>Ramaze is telling you that a visitor&#8217;s browser requested the path &#8216;/&#8217; from the webserver; that is, the root path, just as we have been discussing.</p>

<p>You can press Ctrl-C to stop the server if you want to.  But Ramaze actually doesn&#8217;t need to be stopped and restarted (generally).  Any changes you make to the source code of your application are automatically reloaded and reflected in new browser hits to the site.</p>

<h3>Review</h3>

<p>Let&#8217;s review what we&#8217;ve learned about Ramaze and MVC:</p>

<ul>
<li>Models are our nice, object-oriented read/write interface to the database.</li>
<li>There is generally a one-to-one correspondence between models and database tables.</li>
<li>Create an M4DBI model by subclassing <code>DBI::Model</code>.</li>
<li>Views are the user-facing code; HTML, CSS.</li>
<li>Views are templates: they are mostly constant, with some interpolation of data.</li>
<li>Use <code>#{ ... }</code> in Ramaze templates to interpolate variables and other expressions.</li>
<li>Use <code>&lt;?r ?&gt;</code> to employ flow control and conditional expressions.</li>
<li>Controllers are the crux of your application&#8217;s processing.</li>
<li>Create a controller by subclassing <code>Ramaze::Controller</code>.</li>
<li>Using the class name <code>MainController</code> automatically maps the controller to the root site path (&#8216;/&#8217;).</li>
<li>Instance variables in controller methods are used to make data available to views.</li>
</ul>

<p>We&#8217;ll begin building up the functionality of our application in <a href="http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-6-adding-tasks/">Part 6: Adding Tasks</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example-part-5-controller%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%205%3A%20Controller"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-5-controller/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 4: View</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-4-view/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-4-view/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:41:58 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[ezamar]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[view]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=131</guid>
		<description><![CDATA[This is part 4 of Ramaze by Example, a tutorial on web development.  In Part 3: Model, we coded a model class to interface with the database.

The View part of the MVC pattern is the part of your application you look at.  It is essentially comprised of the static stuff: HTML and CSS. [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 4 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-3-model">Part 3: Model</a>, we coded a model class to interface with the database.</em></p>

<p>The View part of the MVC pattern is the part of your application you look at.  It is essentially comprised of the static stuff: HTML and CSS.  But the pretty picture is not completely inert: some parts are always the same, but other bits vary.  <img src="/wp-content/uploads/ramaze-tutorial/faces-in-cutouts.jpg" style="float: right; margin-top: 0.5em;"/>In other words, views are templates.  You setup the overall picture, and instruct Ramaze where to put the parts of the picture that change. <span id="more-131"></span></p>

<p>By default, Ramaze looks for template files in a <code>view/</code> subdirectory in your project.  Here is a template I made for our application, <code><a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/4-view/view/index.xhtml" target="github">view/index.xhtml</a></code>:</p>


<div class="wp_syntax"><div class="code"><pre class="html4strict" style="font-family:monospace;"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">html</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">head</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">title</span>&gt;</span>Todo List<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">title</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">head</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">body</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>Todo List<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">h1</span>&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
      <span style="color: #009900;">&lt;?r @tasks.each do |task| ?&gt;</span>
        <span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">li</span>&gt;</span>(#{task.status}) #{task.description}<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">li</span>&gt;</span>
      <span style="color: #009900;">&lt;?r end ?&gt;</span>
    <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">ul</span>&gt;</span>
  <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">body</span>&gt;</span>
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">html</span>&gt;</span></pre></div></div>


<p>For the most part, this is just plain HTML.  There are a couple of features that are non-HTML, though.</p>

<p>The first is the <code>&lt;?r ... ?&gt;</code> syntax.  This is the syntax used by Ramaze&#8217;s default templating engine (Ezamar) to inject Ruby flow control and conditional expressions, and any other basic Ruby code you might need to control the dynamic portions of your views.  Ramaze supports <a href="http://ramaze.net/features:templates">many other templating engines</a>, so if you have a preferred templating engine, feel free to go ahead and use it in your own apps.  In this template, we are using <code>&lt;?r ?&gt;</code> to iterate over an array of tasks which has been preprepared for us.  We&#8217;ll cover the details of this preparation in the next part of the tutorial.</p>

<p>The second feature we encounter is the <code>#{ ... }</code> syntax.  This is just plain Ruby string interpolation, and functions just as you would expect: It interpolates the string values of Ruby expressions into your template.</p>

<p>So, as you can see, our template is instructing Ramaze to build an HTML list out of the tasks, with each list item consisting of a task&#8217;s status and description.</p>

<p>The third and final component of MVC is explored in <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-5-controller">Part 5: Controller</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example-part-4-view%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%204%3A%20View"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-4-view/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 3: Model</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-3-model/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-3-model/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:40:11 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[dbi]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[m4dbi]]></category>
		<category><![CDATA[model]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=130</guid>
		<description><![CDATA[This is part 3 of Ramaze by Example, a tutorial on web development.  In Part 2: Base Application, we wrote the main executable Ruby file for our web application.

Now we setup our models.  The models are the Ruby classes that allow us to access the data in the database with Ruby objects instead [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 3 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application">Part 2: Base Application</a>, we wrote the main executable Ruby file for our web application.</em></p>

<p>Now we setup our models.  The models are the Ruby classes that allow us to access the data in the database with Ruby objects instead of awkward things like arrays, hashes or long strings.  Whatever numbers, strings, dates and things are in the database, we can read from model objects.  When we change some data of a model object, a corresponding change occurs in the database.  Models act as our read and write interface to the database. <span id="more-130"></span></p>

<p>We only have one table, so we only have one model.  This one-to-one relationship is typical.  If your app has several tables, you&#8217;d generally have a model for each one, except perhaps association tables.</p>

<p>So here&#8217;s our model code:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Task <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">DBI::Model</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#ff3333; font-weight:bold;">:tasks</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> status
    done ? <span style="color:#996600;">'done'</span> : <span style="color:#996600;">'not done'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>Pretty simple.  Making a model class with M4DBI is as easy as subclassing DBI::Model and passing the name of the table you want to model.  Even having an empty class definition would have provided us with a lot of access and manipulation power, but as you can see, I&#8217;ve also added a helpful method, <code>status</code>, which we can use to turn the plain boolean <code>done</code> column into a clear, informative string.  We&#8217;ll see models in action later in the tutorial.</p>

<p>I&#8217;ve put this code in a file called <code>task.rb</code>, and situated the file under a <code>src/model/</code> directory (in accordance with <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/2-base-app/start.rb#L7">the <code>acquire</code> call in <code>start.rb</code></a>).  Again, this is personal preference.  You can setup your application&#8217;s directory structure however you wish.</p>

<p>Now let&#8217;s learn about the next component of MVC in <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-4-view">Part 4: View</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example-part-3-model%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%203%3A%20Model"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-3-model/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 2: Base Application</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:36:30 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[base]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[start]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=129</guid>
		<description><![CDATA[This is part 2 of Ramaze by Example, a tutorial on web development.  In Part 1: Database Schema, we setup the schema for our database.

The typical base Ramaze application consists of a Ruby script with the command Ramaze.start.  Traditionally this file is called start.rb, but you could name it anything you like.  [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 2 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-1-database-schema">Part 1: Database Schema</a>, we setup the schema for our database.</em></p>

<p>The typical base Ramaze application consists of a Ruby script with the command <code>Ramaze.start</code>.  Traditionally this file is called start.rb, but you could name it anything you like.  Let&#8217;s examine the start.rb I&#8217;ve built (you can view the whole file <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/2-base-app/start.rb" target="github">on github</a> or in your local repo clone). <span id="more-129"></span></p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ramaze'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'m4dbi'</span></pre></div></div>


<p>Require some libraries.  If your system is cool, you can omit &#8220;<code>require 'rubygems'</code>&#8220;.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#ff6633; font-weight:bold;">$db</span> = DBI.<span style="color:#9900CC;">connect</span><span style="color:#006600; font-weight:bold;">&#40;</span> <span style="color:#996600;">'DBI:Pg:todolist'</span>, <span style="color:#996600;">'todolist'</span>, <span style="color:#996600;">''</span> <span style="color:#006600; font-weight:bold;">&#41;</span></pre></div></div>


<p>Connect to the database.  <code>Pg</code> is the DBI driver to use (for PostgreSQL), todolist is both the name of the database and the database user.  The final argument is the database password.  We don&#8217;t ever actually use the database handle (<code>$db</code>) in this tutorial, but if you should ever want to show off your SQL fu in one of your own apps, that&#8217;s what you would use.  For our purposes, we only need to connect so that our ORM can access the database to do its thing.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">acquire <span style="color:#996600;">'src/model/*'</span>
acquire <span style="color:#996600;">'src/*'</span></pre></div></div>


<p>Ramaze provides a nifty little command called <code><a href="http://github.com/manveru/ramaze/tree/a6c24f7d7b767fc9579749a1a8b299c1d0c78a19/lib/ramaze/snippets/ramaze/acquire.rb#L24" target="github">acquire</a></code>.  This works like Ruby&#8217;s normal <code>require</code> command, except you can use wildcards and globs (* and **), like <a href="http://www.ruby-doc.org/core/classes/Dir.html#M002347">the Dir class</a> supports.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;">Ramaze.<span style="color:#9900CC;">start</span> <span style="color:#ff3333; font-weight:bold;">:port</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#006666;">9001</span>, <span style="color:#ff3333; font-weight:bold;">:adapter</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:mongrel</span></pre></div></div>


<p>And finally, press the flipcovered red button to launch.  <code>Ramaze.start</code> can take several configuration options.  Here, we specify the TCP port to listen on, and <a href="http://ramaze.net/features:adapters">which web server adapter</a> to use.</p>

<h3>Review</h3>

<p>Let&#8217;s review what we&#8217;ve learned up to this point.</p>

<ul>
<li>With Ramaze you write very little code.</li>
<li>You understand and know all the code of your app, because you wrote it.</li>
<li><code><a href="http://github.com/manveru/ramaze/tree/a6c24f7d7b767fc9579749a1a8b299c1d0c78a19/lib/ramaze/snippets/ramaze/acquire.rb#L24">acquire</a></code> is like <code>require</code>, but allows wildcards.</li>
<li><code>Ramaze.start</code> is the Ruby code that fires up your Ramaze application.</li>
</ul>

<h3>MVC &#8211; Model, View, Controller</h3>

<p>In web development, there is a way of structuring your code, splitting it into three parts that are separate, yet which still work together.  This architectural pattern is called &#8220;MVC&#8221;.  MVC stands for Model, View, Controller.  When working with Ramaze, you structure your application according to the MVC pattern.</p>

<p>The next three steps of the tutorial will cover each part of MVC.  We&#8217;ll begin with the Model in <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-3-model">Part 3: Model</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example-part-2-base-application%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%202%3A%20Base%20Application"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 1: Database Schema</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-1-database-schema/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-1-database-schema/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:26:17 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[schema]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=128</guid>
		<description><![CDATA[This is part 1 of Ramaze by Example, a tutorial on web development.  In Part 0: Installation and Preparation, we prepared the system by installing the necessary software and libraries.

First, we will design the schema for our database.  We will be making a todo list web application, so we&#8217;re going to need a [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 1 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.  In <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-0-installation-and-preparation/">Part 0: Installation and Preparation</a>, we prepared the system by installing the necessary software and libraries.</em></p>

<p>First, we will design the schema for our database.  We will be making a todo list web application, so we&#8217;re going to need a table for tasks that need to be done.</p>


<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- schema.sql</span>
<span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> tasks <span style="color: #66cc66;">&#40;</span>
    id          SERIAL          <span style="color: #993333; font-weight: bold;">PRIMARY</span> <span style="color: #993333; font-weight: bold;">KEY</span><span style="color: #66cc66;">,</span>
    description VARCHAR<span style="color: #66cc66;">&#40;</span> <span style="color: #cc66cc;">1024</span> <span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
    done        <span style="color: #993333; font-weight: bold;">BOOLEAN</span>         <span style="color: #993333; font-weight: bold;">NOT</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> FALSE
<span style="color: #66cc66;">&#41;</span>;</pre></div></div>


<p>To keep things simple, we won&#8217;t make any other tables (like a users table or a tasklist table).  But let&#8217;s add some sample data: <span id="more-128"></span></p>


<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">-- data.sql</span>
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> tasks <span style="color: #66cc66;">&#40;</span> description <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'Learn Ramaze basics.'</span> <span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> tasks <span style="color: #66cc66;">&#40;</span> description <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'Say hello in Ramaze IRC channel.'</span> <span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> tasks <span style="color: #66cc66;">&#40;</span> description <span style="color: #66cc66;">&#41;</span>
  <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span> <span style="color: #ff0000;">'Write a blog post about Ramaze.'</span> <span style="color: #66cc66;">&#41;</span>;</pre></div></div>


<p>I&#8217;ve placed these two files in an <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/1-database/sql" target="github"><code>sql/</code> subdirectory</a> under the project root.  That&#8217;s a personal practice, but because this is Ramaze, you are free to do as you please &#8212; there are no forced opinions, no conventions you must conform to.</p>

<p>Anyway, that&#8217;s about all we need to do with the database!  If you are an experienced database user and know how to create the tutorial database, make the schema and insert the test data, then feel free to skip the rest of this part and go on to <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application">Part 2: Base Application</a>.  If you need help with any of those steps, continue reading.</p>

<h3>Setting up the database</h3>

<p>PostgreSQL comes with <a href="http://www.postgresql.org/docs/current/interactive/reference-client.html">some convenience tools</a> which you can use to set up the tutorial database.  First, we create a database user specifically for the tutorial.  At your shell prompt, type:</p>

<pre><code>createuser -U postgres -S -D -R todolist
</code></pre>

<p>This makes a user named &#8220;todolist&#8221;.  (Run <code>createuser --help</code> if you want to know what the options do.)  Then we&#8217;ll make the database:</p>

<pre><code>createdb -U postgres -O todolist todolist
</code></pre>

<p>Once that&#8217;s done, we make the schema in the database:</p>

<p><code>cat <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/1-database/sql/schema.sql" target="github">sql/schema.sql</a> | \<br/>psql -U todolist todolist</code></p>

<p>And populate the table with the sample data:</p>

<p><code>cat <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/1-database/sql/data.sql" target="github">sql/data.sql</a> | \<br/>psql -U todolist todolist</code></p>

<p>And that&#8217;s it!  Go now to <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application">Part 2: Base Application</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example-part-1-database-schema%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%201%3A%20Database%20Schema"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-1-database-schema/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example &#8211; Part 0: Installation and Preparation</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-0-installation-and-preparation/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-0-installation-and-preparation/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:20:15 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[dbi]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[m4dbi]]></category>
		<category><![CDATA[mongrel]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubygem]]></category>
		<category><![CDATA[rubygems]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=127</guid>
		<description><![CDATA[This is part 0 of Ramaze by Example, a tutorial on web development.

To install Ramaze, simply install the gem like you would any other gem:

gem install ramaze


Because this is a demonstration of real-world usage, we&#8217;ll use a proper HTTP server and adapter.  Grab Mongrel and its dependencies:

gem install mongrel


You will not need a full [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p><em>This is part 0 of <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/">Ramaze by Example</a>, a tutorial on web development.</em></p>

<p>To install Ramaze, simply install the gem like you would any other gem:</p>

<pre><code>gem install ramaze
</code></pre>

<p>Because this is a demonstration of real-world usage, we&#8217;ll use a proper HTTP server and adapter.  Grab Mongrel and its dependencies:</p>

<pre><code>gem install mongrel
</code></pre>

<p>You will not need a full blown web server such as Apache, nginx or lighttpd for this tutorial.  A production deployment most likely will use one of these.  If, after finishing this tutorial, you want more details on using Ramaze with a web server, see the <a href="http://ramaze.net/deploying">Deployment</a> section of the Ramaze wiki.  <span id="more-127"></span></p>

<p>I will not cover PostgreSQL installation here.  OSX and most Linux distros will have packages for it, so you can use your distro&#8217;s package manager to install it.  For Windows, you have a choice of <a href="http://www.postgresql.org/download/windows">two installers</a>.  If you want to get down and dirty, there are <a href="http://www.postgresql.org/docs/current/static/installation.html">full installation instructions</a> on the PostgreSQL website.</p>

<p>M4DBI installation is done via gems as well:</p>

<pre><code>gem install m4dbi
gem install dbd-pg
</code></pre>

<p>Installing m4dbi will pull the dbi gem as well, as a dependency.  dbd-pg is the DBD we need to use with DBI for PostgreSQL.  It will pull the pg gem as a dependency.</p>

<p>This tutorial was made, run and tested using the following software versions:</p>

<ul>
<li>Ruby 1.8.7</li>
<li>Ramaze 2008.10</li>
<li>DBI 0.4.0</li>
<li>M4DBI 0.6.0</li>
<li>dbd-pg 0.3.5</li>
<li>pg (gem) 0.7.9.2008.10.05</li>
<li>PostgreSQL 8.3.1</li>
<li>mongrel 1.1.5</li>
</ul>

<p>Note that pg-0.7.9.2008.10.13 is known to be incompatible with DBI 0.4.0, so make sure you&#8217;re not using that version.  If necessary, specify an exact version, like:</p>

<pre><code>gem uninstall pg
gem install --version 0.7.9.2008.10.05 pg
</code></pre>

<p>Next, we initialize things in PostgreSQL in <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-1-database-schema">Part 1: Database Schema</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example-part-0-installation-and-preparation%2F&amp;linkname=Ramaze%20by%20Example%20%26%238211%3B%20Part%200%3A%20Installation%20and%20Preparation"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-0-installation-and-preparation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ramaze by Example</title>
		<link>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/#comments</comments>
		<pubDate>Tue, 18 Nov 2008 18:18:10 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[dbi]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[m4dbi]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=126</guid>
		<description><![CDATA[

Table of Contents

Introduction
Part 0: Installation and Preparation
Part 1: Database Schema
Part 2: Base Application
Part 3: Model
Part 4: View
Part 5: Controller
Part 6: Adding Tasks
Part 7: Checking off Tasks
Part 8: Deleting Tasks
Part 9: Layout
Part 10: Cosmetics
Part 11: Validation and Error Handling
Conclusion



What&#8217;s Ramaze?

Ramaze is a fabulous framework that lets you create web applications in Ruby with a minimum of [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<div style="border: 1px solid #000000; background-color: #E6F0FF; padding: 0.5em; margin-bottom: 1.5em; font-size: 12px; line-height: 1.2em;">

<b>Table of Contents</b>
<ul style="margin-top: 0.5em; margin-bottom: 0.5em;">
<li><a href="#introduction">Introduction</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-0-installation-and-preparation/">Part 0: Installation and Preparation</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-1-database-schema/">Part 1: Database Schema</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-2-base-application/">Part 2: Base Application</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-3-model/">Part 3: Model</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-4-view/">Part 4: View</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-5-controller/">Part 5: Controller</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/20/ramaze-by-example-part-6-adding-tasks/">Part 6: Adding Tasks</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/21/ramaze-by-example-part-7-checking-off-tasks/">Part 7: Checking off Tasks</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/22/ramaze-by-example-part-8-deleting-tasks/">Part 8: Deleting Tasks</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/23/ramaze-by-example-part-9-layout/">Part 9: Layout</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/24/ramaze-by-example-part-10-cosmetics/">Part 10: Cosmetics</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/25/ramaze-by-example-part-11-validation-and-error-handling/">Part 11: Validation and Error Handling</a></li>
<li><a href="http://blog.purepistos.net/index.php/2008/11/26/ramaze-by-example-conclusion/">Conclusion</a></li>
</ul>
</div>

<h3 id="introduction">What&#8217;s Ramaze?</h3>

<p><a href="http://ramaze.net">Ramaze</a> is a fabulous framework that lets you create web applications in Ruby with a minimum of code.</p>

<h3>Why Ramaze?</h3>

<p>With king of the hill <a href="http://www.rubyonrails.org/">Rails</a> chugging along, and up-and-comer <a href="http://www.merbivore.com/">Merb</a> picking up steam, why bother with Ramaze?  <span id="more-126"></span>  (If you don&#8217;t care about the rationale, you can <a href="#tutorial">skip right to the beginning of the tutorial</a>.)</p>

<p>The number one<a href="#one-thing" id="one">*</a> thing that makes Ramaze stand out from the crowd is that <strong>you write very little code</strong> and <strong>you write it all yourself</strong>.  No generators.</p>

<p><img src="/wp-content/uploads/ramaze-tutorial/shocked.jpg" style="float: left; margin-right: 1em;" alt=":O"/> <em>&#8220;No generators!?  How will I survive?  What kind of mad scheme is this?&#8221;</em>  Relax.  It&#8217;s all good.  Why?  It&#8217;s all a matter of philosophy.</p>

<h4>The Ramaze philosophy</h4>

<p>Before Rails, people wrote lots and lots of code when making a web app, and they did it over and over as they did web app after web app.  With each new app, they would spend time &#8220;ramping up&#8221; with just the base application before they got into the real meat of the matter, the core functionality which varied from client to client, application to application.  Rails and Merb and their ilk try to make your life easier by generating this &#8220;lots and lots of code&#8221; for you, so you don&#8217;t have to spend time repeating the motions of getting the skeleton of your application coded.</p>

<p>Ramaze takes a different approach.  It asks: How about we dump the &#8220;lots and lots of code&#8221; part altogether?  This way, you get the benefit of nearly nil ramp up time, without the gaping jaw effect that hits you after you run a code generator script and sit staring at the big filetree that just sprouted out of the ground (think <a href="http://en.wikipedia.org/wiki/Jack_and_the_beanstalk">Jack and the Beanstalk</a>).</p>

<p>So yeah, it&#8217;s a matter of philosophy.  Sure, the Rails way works for some people.  And that&#8217;s cool.  But if you&#8217;re the kind of person who went to your local neighbourhood Rails tutorial, got to the generator part, and went &#8220;Okay, what the heck is all this stuff&#8230; I thought we were making a Hello World app?&#8221; &#8212; well by jove, you&#8217;ve come to the right place at the right time.  Come!  Come, and I will show you a wonderful world where it needn&#8217;t be so.  A world where your code is tiny, yet powerful, and you understand it all, because it was generated &#8212; not by a script that someone else wrote &#8212; but by your own God-given clever little noodle.</p>

<h3 id="tutorial">Web development by example: A Ramaze tutorial</h3>

<p><em>Update: This tutorial applies to Ramaze 2009.03 and prior.  It probably won&#8217;t work under Ramaze 2009.04+.</em></p>

<p>Thus begins our adventure into Ramaze, the web framework.  I will lead you through the making of a non-trivial Ramaze application, using the same parts and features you would use in your own killer, take-the-world-by-storm web app.  You will come to know all the basics, and perhaps even some advanced things, too.  Along with Ramaze, I will make use of a real-world database and ORM.  My personal choices for these are <a href="http://www.postgresql.org/">PostgreSQL</a> and <a href="http://purepistos.net/m4dbi">M4DBI</a>, but the same techniques and principles easily apply to other options like <a href="http://www.mysql.com/">MySQL</a>, <a href="http://www.sqlite.org/">SQLite</a>, <a href="http://sequel.rubyforge.org/">Sequel</a> and <a href="http://www.datamapper.org/doku.php">DataMapper</a>.  I may cover usage of these in the future.</p>

<p>This tutorial is based on the earlier work of <a href="https://github.com/manveru">manveru</a>, namely his <a href="http://ramaze.net/tutorials:todolist">todolist tutorial</a>.  It is similar to that one in some ways, but differs in other ways.  That tutorial is still a good reference, though, so you may wish to go over it when you&#8217;re done with this one.</p>

<p>You should have some familiarity with the basics of Ruby and HTML to learn and use Ramaze, but you need not have any prior experience with web frameworks in general.  In fact, you are at an advantage if you do not, since you won&#8217;t have any preconceptions, habits or conventions that might negatively bias your first impressions and experiences.</p>

<h3>Source Code</h3>

<p>The full source code for this repository is available <a href="http://github.com/Pistos/ramaze-todolist-tutorial/tree/master">at github.com</a>.  Each step of the tutorial is a separate branch which builds upon the previous step.  To get the code, you should use <a href="http://git.or.cz/">git</a>, the great version control system.</p>

<pre><code>git clone git://github.com/Pistos/ramaze-todolist-tutorial.git
</code></pre>

<p>If you really don&#8217;t want to get or use git, github has download links you can use.  You can also browse the code online at github by hovering over the &#8220;all branches&#8221; tab in the menu bar and selecting a branch.  I recommend you use git itself, though, because you will be able to easily switch between branches as we progress through the tutorial:</p>

<pre><code>git checkout 1-database
</code></pre>

<p>and you&#8217;ll also be able to see what was added and what changed in the codebase from step to step:</p>

<pre><code>git diff 5-controller 6-add-task
</code></pre>

<h3>Live Support</h3>

<p>The Ramaze community is most active in IRC.  Our home channel is <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23ramaze">#ramaze on irc.freenode.net</a>.  If you have any questions before, while or after going through this tutorial, feel free to drop by.  I myself (Pistos) am there from time to time, but there are usually others around available to answer questions.  There&#8217;s also <a href="http://groups.google.com/group/ramaze">the Ramaze mailing list</a>.</p>

<p>So let&#8217;s begin with <a href="http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example-part-0-installation-and-preparation/">Part 0: Installation and Preparation</a>.</p>

<hr />

<p><a href="#one" id="one-thing">*</a> <a href="http://people.csail.mit.edu/paulfitz/spanish/t2.html">&#8220;Our chief weapon is surprise&#8230;surprise and fear&#8230;fear and surprise!&#8221;</a></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F18%2Framaze-by-example%2F&amp;linkname=Ramaze%20by%20Example"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/18/ramaze-by-example/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>Diakonos &#8211; version 0.8.6</title>
		<link>http://blog.purepistos.net/index.php/2008/11/02/diakonos-version-086/</link>
		<comments>http://blog.purepistos.net/index.php/2008/11/02/diakonos-version-086/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 02:48:39 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[align]]></category>
		<category><![CDATA[built-in]]></category>
		<category><![CDATA[column]]></category>
		<category><![CDATA[columnize]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[format]]></category>
		<category><![CDATA[formatting]]></category>
		<category><![CDATA[help]]></category>
		<category><![CDATA[new]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[system]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>
		<category><![CDATA[word]]></category>
		<category><![CDATA[wrap]]></category>

		<guid isPermaLink="false">1593000750</guid>
		<description><![CDATA[Version 0.8.6 of Diakonos is now available.  Install by gem install diakonos.  I&#8217;ve been on a bit of a tear lately with development, and as a result, we have several nice new features in Diakonos.

Users can now define their own custom status variables to display whatever they want on the Diakonos status line. [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.6 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.  Install by <code>gem install diakonos</code>.  I&#8217;ve been on a bit of a tear lately with development, and as a result, we have several nice new features in Diakonos.</p>

<p>Users can now define their own custom <strong>status variables</strong> to display whatever they want on the Diakonos status line.  As an example, I&#8217;ve placed <a href="http://github.com/Pistos/diakonos/tree/master/scripts/git-branch.rb">a git branch script</a> in a new <a href="http://github.com/Pistos/diakonos/tree/master/scripts">scripts directory</a> of <a href="http://github.com/Pistos/diakonos/tree/master">the source code repository</a>.  It demonstrates how to use hooks and status variables to show the git branch the current file belongs to, if the file is in a git repository.</p>

<p>Diakonos now accepts a -m (&#8211;open-matching) argument which will open all files in the current directory subtree which match the given regular expression &#8212; a sort of &#8220;<strong>grep and open</strong>&#8220;.</p>

<p>A few formatting features were added.  First, the long-awaited <strong>comment and uncomment functions</strong>.  As you&#8217;ve come to expect with Diakonos, comment characters are language specific and completely customizable.  I also added a function to <strong>hard wrap text</strong> at a margin.  As well, the snazzy new <strong>columnize</strong> function was added.  Watch how to use it in this mini screencast:</p>

<p><center><OBJECT CLASSID="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" WIDTH="361" HEIGHT="393" CODEBASE="http://active.macromedia.com/flash5/cabs/swflash.cab#version=5,0,0,0">
<PARAM NAME=movie VALUE="columnize.swf">
<PARAM NAME=play VALUE=true>
<PARAM NAME=loop VALUE=false>
<PARAM NAME=quality VALUE=low>
<EMBED SRC="/wp-content/uploads/diakonos/columnize.swf" WIDTH=361 HEIGHT=393 quality=low loop=false TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
</EMBED>
</OBJECT>
</center></p>

<p>Finally, I am very pleased to present in this latest Diakonos version the brand new <strong>built-in help system</strong>.  Up till now, the &#8220;help&#8221; provided by the F1 key has been &#8230; well it&#8217;s been borderline useless.  (For those of you that don&#8217;t know, all it did was list all the mappings of keys to functions, in a not so user friendly way.)  But with 0.8.6, you are brought into an interactive, searchable help system which has a growing number of documents that cover many aspects of Diakonos from usage to configuration to default keys to tips and tricks.  I&#8217;d tell you more &#8212; but I want you to try it!  I&#8217;ve designed it to further my goal of Diakonos being the most user friendly console text editor available for Linux.  If Diakonos falls short of this, <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes">I want to know</a>.</p>

<p>The rest of the changes are described in this version&#8217;s full <a href="http://github.com/Pistos/diakonos/tree/v0.8.6/CHANGELOG">changelog</a>:</p>

<ul>
<li>Find-as-you-type added.</li>
<li>Help system added.</li>
<li>print_mapped_function added.</li>
<li>User-definable status line variables added.</li>
<li>:after_open and :after_buffer_switch hooks added.</li>
<li>Sample script for git branch status variable added.</li>
<li>comment_out and uncomment functions added.</li>
<li>comment_string and comment_close_string settings added.</li>
<li>Added -m (&#8211;open-matching) command line argument.</li>
<li>wrap_paragraph function and wrap_margin setting added for hard wrapping text.</li>
<li>columnize function and column_delimiter setting added.</li>
<li>Numerous small fixes, adjustments and refactorings.</li>
</ul>

<p>Report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>, or come <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes">visit me in IRC</a>!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F11%2F02%2Fdiakonos-version-086%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.6"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/11/02/diakonos-version-086/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to exclude directories with tar</title>
		<link>http://blog.purepistos.net/index.php/2008/10/27/how-to-exclude-directories-with-tar/</link>
		<comments>http://blog.purepistos.net/index.php/2008/10/27/how-to-exclude-directories-with-tar/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 13:57:06 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[archive]]></category>
		<category><![CDATA[arg]]></category>
		<category><![CDATA[args]]></category>
		<category><![CDATA[argument]]></category>
		<category><![CDATA[arguments]]></category>
		<category><![CDATA[bzip]]></category>
		<category><![CDATA[bzip2]]></category>
		<category><![CDATA[dir]]></category>
		<category><![CDATA[directories]]></category>
		<category><![CDATA[directory]]></category>
		<category><![CDATA[exclude]]></category>
		<category><![CDATA[excluding]]></category>
		<category><![CDATA[exclusion]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[files]]></category>
		<category><![CDATA[how]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[option]]></category>
		<category><![CDATA[options]]></category>
		<category><![CDATA[param]]></category>
		<category><![CDATA[parameter]]></category>
		<category><![CDATA[parameters]]></category>
		<category><![CDATA[params]]></category>
		<category><![CDATA[tar]]></category>
		<category><![CDATA[tarball]]></category>
		<category><![CDATA[to]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=124</guid>
		<description><![CDATA[For a long time I had been unable to determine just how to exclude directories from a tarring operation.  Surface googleage never helped.  I have, however, (with some help) finally determined how to do this rather smoothly.  Given a directory tree structure like this

/wanted-dir-1
/wanted-dir-1/wanted-subdir-1
/wanted-dir-1/wanted-subdir-2
/wanted-dir-1/unwanted-subdir-1
/wanted-dir-1/wanted-subdir-3
/wanted-dir-1/unwanted-subdir-2
.....


Your syntax should be as follows:

tar cjvf tarball.tar.bz2 --exclude [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>For a long time I had been unable to determine just how to exclude directories from a tarring operation.  Surface googleage never helped.  I have, however, (with some help) finally determined how to do this rather smoothly.  Given a directory tree structure like this</p>

<pre><code>/wanted-dir-1
/wanted-dir-1/wanted-subdir-1
/wanted-dir-1/wanted-subdir-2
/wanted-dir-1/unwanted-subdir-1
/wanted-dir-1/wanted-subdir-3
/wanted-dir-1/unwanted-subdir-2
.....
</code></pre>

<p>Your syntax should be as follows:</p>

<pre><code>tar cjvf tarball.tar.bz2 --exclude unwanted-subdir-1 \
[--exclude unwanted-subdir-2...] wanted-dir-1 \
[wanted-dir-2...]
</code></pre>

<p>The critical part that I was not cluing into was that the &#8216;f&#8217; option/command of tar expected the tarball filename (tarball.tar.bz2 in the above example) to immediately follow it.  For example, this will NOT work:</p>

<pre><code>tar cjvf --exclude unwanted-dir tarball.tar.bz2 \
wanted-dir
</code></pre>

<p>and it will, in fact, create a file literally named &#8220;&#8211;exclude&#8221; in the current directory.</p>

<p>Hope this helps some frustrated souls.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F10%2F27%2Fhow-to-exclude-directories-with-tar%2F&amp;linkname=How%20to%20exclude%20directories%20with%20tar"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/10/27/how-to-exclude-directories-with-tar/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Diakonos &#8211; version 0.8.5</title>
		<link>http://blog.purepistos.net/index.php/2008/10/03/diakonos-version-084-2/</link>
		<comments>http://blog.purepistos.net/index.php/2008/10/03/diakonos-version-084-2/#comments</comments>
		<pubDate>Fri, 03 Oct 2008 17:56:16 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[256]]></category>
		<category><![CDATA[clipboard]]></category>
		<category><![CDATA[color]]></category>
		<category><![CDATA[colors]]></category>
		<category><![CDATA[colour]]></category>
		<category><![CDATA[colours]]></category>
		<category><![CDATA[curses]]></category>
		<category><![CDATA[dcop]]></category>
		<category><![CDATA[diakonos]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[kde]]></category>
		<category><![CDATA[klipper]]></category>
		<category><![CDATA[release]]></category>
		<category><![CDATA[text]]></category>
		<category><![CDATA[version]]></category>

		<guid isPermaLink="false">224472516</guid>
		<description><![CDATA[Version 0.8.5 of Diakonos is now available.  Install by gem install diakonos.  I&#8217;m pleased to introduce several nice features in this version.

If your terminal supports 256 colours, Diakonos syntax highlighting can now employ 256 colours (instead of the usual 16).  See diakonos-256-colour.conf which comes with the 0.8.5 package.

I have also added the [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Version 0.8.5 of <a href="http://purepistos.net/diakonos">Diakonos</a> is now available.  Install by <code>gem install diakonos</code>.  I&#8217;m pleased to introduce several nice features in this version.</p>

<p>If your terminal supports 256 colours, Diakonos syntax highlighting can now employ 256 colours (instead of the usual 16).  See <a href="http://github.com/Pistos/diakonos/tree/master/diakonos-256-colour.conf">diakonos-256-colour.conf</a> which comes with the 0.8.5 package.</p>

<p>I have also added the ability to synchronize the Diakonos clipboard with the KDE clipboard (via <a href="http://en.wikipedia.org/wiki/Dcop">DCOP</a> and <a href="http://en.wikipedia.org/wiki/Klipper">Klipper</a>).  If you are using KDE and have DCOP installed, activate this feature by using <a href="http://github.com/Pistos/diakonos/tree/8575ba5403557da0940b25db2732ddfe829a6f17/diakonos.conf#L268">these lines</a> which are commented out in the default configuration file.</p>

<p>Some of you may also have noticed that I&#8217;ve recently overhauled <a href="http://purepistos.net/diakonos">the Diakonos homepage</a>.  Have a look if you haven&#8217;t already!</p>

<p>The other changes are detailed in the actual changelog:</p>

<ul>
<li>Added 256 colour support.</li>
<li>Added support for opening files with &#8220;filepath:linenumber&#8221; syntax.</li>
<li>Added ability to put %_ in a code closer as the place to position the cursor.</li>
<li>Code closers can now contain newlines.</li>
<li>Now closer text is parsed-indented by default.</li>
<li>Added integration with Klipper (KDE clipboard).</li>
<li>Added support for regexp match placeholders (\1, \2, etc.) in findAndReplace.</li>
<li>Added eol_behaviour setting.</li>
<li>Various minor bug fixes.</li>
<li>Changed to MIT licence.</li>
</ul>

<p>Report any bugs <a href="http://linis.purepistos.net/ticket/list/Diakonos">here</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F10%2F03%2Fdiakonos-version-084-2%2F&amp;linkname=Diakonos%20%26%238211%3B%20version%200.8.5"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/10/03/diakonos-version-084-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ramaze + Phusion Passenger</title>
		<link>http://blog.purepistos.net/index.php/2008/10/02/ramaze-phusion-passenger/</link>
		<comments>http://blog.purepistos.net/index.php/2008/10/02/ramaze-phusion-passenger/#comments</comments>
		<pubDate>Thu, 02 Oct 2008 19:14:08 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[application]]></category>
		<category><![CDATA[config]]></category>
		<category><![CDATA[configuration]]></category>
		<category><![CDATA[configure]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[demonstration]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[phusion]]></category>
		<category><![CDATA[rack]]></category>
		<category><![CDATA[rackup]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[setup]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=121</guid>
		<description><![CDATA[As some of you may know, I am a relatively active member of the Ramaze community.  I have seen an increase in incidents of people asking for help getting Ramaze to run under Phusion Passenger.  I decided to see just how hard the setup would be, with the intention of documenting it for [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>As some of you may know, I am a relatively active member of the <a href="http://ramaze.net">Ramaze</a> community.  I have seen an increase in incidents of people asking for help getting Ramaze to run under Phusion Passenger.  I decided to see just how hard the setup would be, with the intention of documenting it for the Ramaze community.  I succeeded in running a basic Hello World application, so here are the steps I took.</p>

<h3>Create a simple Ramaze app</h3>

<p>Even if you have an existing Ramaze app that you will use instead of this little demo app, you should read this section because I talk about important pitfalls that can cause things to break.  You can apply the same ideas to your app.</p>

<p>As per <a href="http://www.modrails.com/documentation/Users%20guide.html#_deploying_a_rack_based_ruby_application">the Passenger User&#8217;s Guide</a>, I created a <code>tmp/</code> directory under the root of the Ramaze app.  Passenger needs this directory (see <a href="http://www.modrails.com/documentation/Users%20guide.html#_redeploying_restarting_the_ruby_on_rails_application">the User Guide</a> if you want to know why).  I also made a <code>public/</code> directory, which is a standard part of Ramaze apps in general.</p>

<p>Afterwards, I crafted a basic one-file Ramaze app in <code>start.rb</code> (the standard filename for the executable in Ramaze apps), and a <code>config.ru</code> file, which is needed by Rack.  (<a href="http://rack.rubyforge.org/">Rack</a> is the interface layer between Ramaze and Apache.)</p>

<h4>start.rb</h4>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'ramaze'</span>
<span style="color:#9966CC; font-weight:bold;">class</span> MainController <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">Ramaze::Controller</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> index
    <span style="color:#996600;">'hi'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>


<p>A <strong>critical</strong> thing to note about this Ramaze app is that <em>there is no Ramaze.start command</em>.  If you put it, the whole jalopy will fall apart &#8212; so don&#8217;t put that in your app.  If you have a legacy app that you want to start running under Passenger, comment out or remove the existing Ramaze.start line.</p>

<h4>config.ru</h4>


<div class="wp_syntax"><div class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'start'</span>
Ramaze.<span style="color:#9900CC;">trait</span><span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:essentials</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">delete</span> <span style="color:#6666ff; font-weight:bold;">Ramaze::Adapter</span>
Ramaze.<span style="color:#9900CC;">start</span>!
run <span style="color:#6666ff; font-weight:bold;">Ramaze::Adapter::Base</span></pre></div></div>


<p>This is the standard &#8220;<a href="http://rack.rubyforge.org/doc/classes/Rack/Builder.html">rackup</a>&#8221; file that comes with Ramaze.  I didn&#8217;t make any changes to it, but I should point out that <a href="http://www.modrails.com/documentation/Users%20guide.html#_ramaze">the rackup file that was shown on the Passenger site</a> was out of date.</p>

<h4>Overview</h4>

<p>So, to recap, my basic little app had these four things:</p>

<pre><code>  public/
  tmp/
  config.ru
  start.rb
</code></pre>

<h3>Install Passenger</h3>

<p>If you are intending to run a Ramaze app under a web host that already offers Passenger to its users, you can obviously skip this section.</p>

<p>As per <a href="http://www.modrails.com/install.html">the Install page of the Passenger website</a>, I simply ran</p>

<pre><code>  gem install passenger
</code></pre>

<p>and</p>

<pre><code>  passenger-install-apache2-module
</code></pre>

<p>I did this as root, but it looks possible to do so as a non-root user.  The Passenger installation script was straight forward, and required no interaction on my part other than to confirm my desire to proceed with the installation.  It is sufficiently verbose enough for you to see it compile and install things under your /usr/lib/ruby tree.  When it&#8217;s done, it clearly displays some lines for you to put into your Apache configuration file.  In my case:</p>

<pre><code> LoadModule passenger_module /usr/lib/ruby/..../mod_passenger.so
 PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-2.0.3
 PassengerRuby /usr/bin/ruby18
</code></pre>

<p>I obediently pasted that into the main Apache config.  It then shows a sample virtual host configuration that you can use as a skeleton:</p>

<pre><code> &lt;VirtualHost *:80&gt;
    ServerName www.yourhost.com
    DocumentRoot /somewhere/public
 &lt;/VirtualHost&gt;
</code></pre>

<p>I copied that into my virtual host config file, and adjusted the hostname and changed the document root to the full, absolute path of the <code>public/</code> directory of my Ramaze app.</p>

<h4>Restart Apache</h4>

<p>I restarted Apache to get all my configuration changes active.</p>

<h3>Run the app</h3>

<p>At this point, my Ramaze app was ready to run under Passenger, so I browsed to <code>http://myhostname</code> and saw &#8220;hi&#8221; displayed, as expected.  To see a little detail (or to troubleshoot problems), examine your Apache logs.  You should see all output from Ramaze piped there.</p>

<p>I hope this helps people who are trying to run Ramaze under Passenger!  If you need further assistance please visit our support channel, <a href="http://mibbit.com/?server=irc.freenode.net&amp;channel=%23mathetes">#ramaze</a> on the FreeNode IRC network, or try the <a href="http://groups.google.com/group/ramaze">discussion group</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F10%2F02%2Framaze-phusion-passenger%2F&amp;linkname=Ramaze%20%2B%20Phusion%20Passenger"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/10/02/ramaze-phusion-passenger/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Don&#8217;t try this in Firefox</title>
		<link>http://blog.purepistos.net/index.php/2008/10/01/dont-try-this-in-firefox/</link>
		<comments>http://blog.purepistos.net/index.php/2008/10/01/dont-try-this-in-firefox/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 17:38:23 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[alert]]></category>
		<category><![CDATA[box]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[bug]]></category>
		<category><![CDATA[dialog]]></category>
		<category><![CDATA[dialogue]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[flaw]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[hci]]></category>
		<category><![CDATA[modal]]></category>
		<category><![CDATA[opera]]></category>
		<category><![CDATA[pop-up]]></category>
		<category><![CDATA[popup]]></category>
		<category><![CDATA[problem]]></category>
		<category><![CDATA[trap]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[usability]]></category>
		<category><![CDATA[window]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=120</guid>
		<description><![CDATA[Try the live demo of a Firefox trap, or read on first.  I recommend not visiting that page with Firefox.

I was doing some Javascript debugging today, and observed what I think is a design flaw in Firefox (and perhaps in GUI applications in general).  The Firefox alert box is modal.  From Wikipedia:




 [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>Try the live demo of <a href="http://purepistos.net/firefox-trap.html" target="external">a Firefox trap</a>, or read on first.  I recommend not visiting that page with Firefox.</p>

<p>I was doing some Javascript debugging today, and observed what I think is a design flaw in Firefox (and perhaps in GUI applications in general).  The Firefox alert box is modal.  From <a href="http://en.wikipedia.org/wiki/Modal_window">Wikipedia</a>:</p>

<p><span id="more-120"></span></p>

<blockquote>
  <p>a modal window is a child window which requires the user to interact with it before they can return to operating the parent application, thus preventing the workflow on the application main window</p>
</blockquote>

<p>Now, the modality of the alert popup is nothing to be too alarmed about, but its inaptness became magnified because I happened to put an alert statement in a loop of sorts, causing 40+ alert boxes to show up.  Not all at once; one after another, requiring acknowledgement of each and every one.  The killer part: You can&#8217;t do anything with Firefox while an alert box is displayed (short of <a href="http://en.wikipedia.org/wiki/Signal_%28computing%29">SIGnalling</a> the process). Technically speaking, you have a brief window of a few milliseconds between alert boxes in which you can sneak in a little bit of interaction (a keypress or mouse click).</p>

<p>Overall, the experience was inconvenient at best, irritating at worst.</p>

<p>It brings to mind the general issue with GUI applications where you might be typing or otherwise interacting with an application, and a dialogue box will pop up, interrupting your typing or clicking, and capturing (or discarding) your keystrokes or clicks.  This brings up the usability question:</p>

<p>Does <em>any</em> popup deserve to be modal?</p>

<p>I might wager to say: no.  I would not be against having message boxes that popped <em>under</em>, with some sort of humble blinking (say, a flashing entry in the taskbar) informing me that something deserves my attention.  I can&#8217;t think of a time when I was glad to have a popup interrupt my typing.  Every single experience was one of annoyance or infuriation.</p>

<p>It was pointed out to me that Firefox add-ons (like <a href="http://noscript.net/">NoScript</a>) can help protect you from falling into the trap.</p>

<p>Anyway, it deserves to be said that the clever folks at <a href="http://www.opera.com/">Opera</a> Software did something right in putting a feature on every alert box: A checkbox to stop the madness if you so desire.  Try <a href="http://purepistos.net/firefox-trap.html">the demo page</a> again in Opera, and see the difference.  It would be good if Firefox did something similar.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F10%2F01%2Fdont-try-this-in-firefox%2F&amp;linkname=Don%26%238217%3Bt%20try%20this%20in%20Firefox"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/10/01/dont-try-this-in-firefox/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>There is no such thing as right or wrong!</title>
		<link>http://blog.purepistos.net/index.php/2008/10/01/there-is-no-such-thing-as-right-or-wrong/</link>
		<comments>http://blog.purepistos.net/index.php/2008/10/01/there-is-no-such-thing-as-right-or-wrong/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 12:41:06 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Religion]]></category>
		<category><![CDATA[ethics]]></category>
		<category><![CDATA[moral]]></category>
		<category><![CDATA[morality]]></category>
		<category><![CDATA[relative]]></category>
		<category><![CDATA[relativism]]></category>
		<category><![CDATA[right]]></category>
		<category><![CDATA[subjective]]></category>
		<category><![CDATA[subjectivism]]></category>
		<category><![CDATA[wrong]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=119</guid>
		<description><![CDATA[I was musing recently about subjective morality, and thought of something that I found rather amusing:


  &#8220;There is no such thing as right or wrong.&#8221;
  [ ] Right &#160; [ ] Wrong


  


No related posts.


No related posts.]]></description>
			<content:encoded><![CDATA[<p>I was musing recently about subjective morality, and thought of something that I found rather amusing:</p>

<blockquote>
  <p>&#8220;There is no such thing as right or wrong.&#8221;<br/>
  [ ] Right &nbsp; [ ] Wrong</p>
</blockquote>

<p> <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F10%2F01%2Fthere-is-no-such-thing-as-right-or-wrong%2F&amp;linkname=There%20is%20no%20such%20thing%20as%20right%20or%20wrong%21"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/10/01/there-is-no-such-thing-as-right-or-wrong/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Rails&#8217; memoization is not always faster</title>
		<link>http://blog.purepistos.net/index.php/2008/09/29/rails-memoization-is-not-always-faster/</link>
		<comments>http://blog.purepistos.net/index.php/2008/09/29/rails-memoization-is-not-always-faster/#comments</comments>
		<pubDate>Mon, 29 Sep 2008 15:57:11 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[activesupport]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[benchmarking]]></category>
		<category><![CDATA[cache]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[efficiency]]></category>
		<category><![CDATA[memo]]></category>
		<category><![CDATA[memoizable]]></category>
		<category><![CDATA[memoization]]></category>
		<category><![CDATA[memoize]]></category>
		<category><![CDATA[method]]></category>
		<category><![CDATA[mixin]]></category>
		<category><![CDATA[module]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[speed]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=118</guid>
		<description><![CDATA[I was chatting in #ruby-pro (on Freenode) with some folks, and the topic of memoization came up.  raggi expressed his sentiment that

[the rails devs] over-memoize waaaay too much.  some of these methods will be faster running than looking up from memoize. in the case of certain rails code, it seems to be applied [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>I was chatting in #ruby-pro (on Freenode) with some folks, and the topic of <a href="http://en.wikipedia.org/wiki/Memoization">memoization</a> came up.  <a href="http://github.com/raggi">raggi</a> expressed his sentiment that</p>

<blockquote>[the rails devs] over-memoize waaaay too much.  some of these methods will be faster running than looking up from memoize. in the case of certain rails code, it seems to be applied to any method that is stable, regardless of complexity or input</blockquote>

<p><a href="http://github.com/apeiros">apeiros</a> commented that</p>

<blockquote>it&#8217;s often overmedication too since a simple <code>def foo; @foo ||= begin; ...longcalc...; end; end</code> would suffice</blockquote>

<p>I do believe that people should not employ memoization too loosely, since I think that if you have a performance problem, you should first try to address it directly rather than blindly treat the symptom simply by slapping a method with the Memoizable mixin.</p>

<p>I asked raggi for an example of the problem, some code that I could run some benchmarks on.  He directed my attention to <a href="http://github.com/rails/rails/tree/master/actionpack/lib/action_controller/request.rb">request.rb of the ActionController module</a>.  Strolling through the code, I saw <a href="http://github.com/rails/rails/commit/b7529ed1cc7cfd8df5fd1b069e2881d39d3d984c#L2R75">a memoized method which did nothing but return a hash value</a>.  apeiros and I thought that it couldn&#8217;t possibly be faster to memoize code like that, so I set out to benchmark some code.</p>

<h4>Benchmark results</h4>

<ul>
<li>Memoizing this method made it <strong>14.5% slower</strong>.</li>
<li>Rails memoization was <strong>57.8% slower</strong> than classic memoization (i.e. <code>@cached_content_length ||= @env['CONTENT_LENGTH'].to_i</code>).  Alternatively phrased: classic memoization was more than twice as fast as Rails&#8217;.</li>
<li>The very act of mixing in Memoizable (without memoizing any methods) incurred an 8.3% speed penalty on method execution.</li>
</ul>

<p>Here are <a href="/wp-content/uploads/memoization/memo-bench.rb">the benchmarking code</a> and <a href="/wp-content/uploads/memoization/memo-bench.results">the full benchmark results</a>.  The code makes use of <a href="http://github.com/Pistos/better-benchmark/tree/master">better-benchmark</a>, my library for statistically correct benchmarking.</p>

<p>So, employ Memoizable judiciously.  Look over your method and consider whether memoization will really improve speed or not.  It&#8217;s not guaranteed to do so in all cases.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F09%2F29%2Frails-memoization-is-not-always-faster%2F&amp;linkname=Rails%26%238217%3B%20memoization%20is%20not%20always%20faster"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/09/29/rails-memoization-is-not-always-faster/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Managing web application errors with Hoptoad and Ramaze</title>
		<link>http://blog.purepistos.net/index.php/2008/09/22/managing-web-application-errors-with-hoptoad-and-ramaze/</link>
		<comments>http://blog.purepistos.net/index.php/2008/09/22/managing-web-application-errors-with-hoptoad-and-ramaze/#comments</comments>
		<pubDate>Tue, 23 Sep 2008 04:42:34 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[errors]]></category>
		<category><![CDATA[exception]]></category>
		<category><![CDATA[exceptions]]></category>
		<category><![CDATA[gem]]></category>
		<category><![CDATA[hoptoad]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ramaze]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubygem]]></category>
		<category><![CDATA[rubygems]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://blog.purepistos.net/?p=117</guid>
		<description><![CDATA[I came across Hoptoad recently.  Hoptoad is basically a webservice with an API that you can post error data to.  It then stores the data and presents it to you in a nice web interface, and optionally sends you e-mail alerts in such a fashion that it doesn&#8217;t just unintelligently flood your inbox.

It [...]


No related posts.]]></description>
			<content:encoded><![CDATA[<p>I came across <a href="http://hoptoadapp.com">Hoptoad</a> recently.  Hoptoad is basically a webservice with an API that you can post error data to.  It then stores the data and presents it to you in a nice web interface, and optionally sends you e-mail alerts in such a fashion that it doesn&#8217;t just unintelligently flood your inbox.</p>

<p>It was originally designed to be used with Rails apps, but I saw that there was also a <a href="http://merbivore.com">Merb</a> plugin.  Not wanting <a href="http://ramaze.net">my favourite web framework</a> to be left out, I made <a href="http://github.com/Pistos/hoptoad-notifier-ramaze">a Hoptoad notifier for Ramaze</a> with the help of <a href="http://github.com/manveru">manveru</a> (the Ramaze lead dev).</p>

<p>Install via Rubygems:</p>

<p><code>
gem install hoptoad-notifier-ramaze --source http://purepistos.net
</code></p>

<p>And usage is dead easy; just two lines:</p>

<p><code>
    require 'hoptoad-notifier'
    Ramaze::Helper::HoptoadNotifier.trait[ :api_key ] = 'your-hoptoad-project-api-key'
</code></p>

<p>I&#8217;m already using it with my own Ramaze applications.  Enjoy!  <img src='http://blog.purepistos.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F09%2F22%2Fmanaging-web-application-errors-with-hoptoad-and-ramaze%2F&amp;linkname=Managing%20web%20application%20errors%20with%20Hoptoad%20and%20Ramaze"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>No related posts.</p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/09/22/managing-web-application-errors-with-hoptoad-and-ramaze/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thomas &#8211; For Thee</title>
		<link>http://blog.purepistos.net/index.php/2008/09/12/thomas-for-thee/</link>
		<comments>http://blog.purepistos.net/index.php/2008/09/12/thomas-for-thee/#comments</comments>
		<pubDate>Fri, 12 Sep 2008 18:50:43 +0000</pubDate>
		<dc:creator>Pistos</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Music]]></category>
		<category><![CDATA[classical]]></category>
		<category><![CDATA[composition]]></category>
		<category><![CDATA[dave]]></category>
		<category><![CDATA[david]]></category>
		<category><![CDATA[free]]></category>
		<category><![CDATA[piano]]></category>
		<category><![CDATA[recording]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[thomas]]></category>

		<guid isPermaLink="false">62080714</guid>
		<description><![CDATA[So I was going through my usual whirl of daily Ruby news sites, and eventually my clickpath led me to a blog post by Dave Thomas wherein he unveils his first composition for piano.  For those of you who don&#8217;t know, Dave Thomas is a well-known figure in the Ruby community, known for co-authoring [...]


Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>So I was going through my usual whirl of daily Ruby news sites, and eventually my clickpath led me to <a href="http://pragdave.blogs.pragprog.com/pragdave/2008/05/so-ive-been-doi.html">a blog post by Dave Thomas</a> wherein he unveils his first composition for piano.  For those of you who don&#8217;t know, Dave Thomas is a well-known figure in the <a href="http://www.ruby-lang.org">Ruby</a> community, known for co-authoring <a href="http://pragprog.com/titles/ruby/programming-ruby">Programming Ruby</a>, one of the most popular books written about the Ruby programming language.</p>

<p>Well, reading the blog post piqued my curiosity because <a href="/index.php/2008/06/16/my-programming-language-is-my-dance-partner/">Ruby is my favourite programming language</a>, and <a href="/index.php/piano/">I&#8217;m also a pianist</a>.  So I examined the PDF of the piece, and thought that it didn&#8217;t look too difficult to play.  I thought this might make a fitting next entry in <a href="/index.php/piano/">my piano recording series</a>.</p>

<p>So here I present my interpretation and rendition of Dave Thomas&#8217; piece, <i>For Thee</i>.  I took some liberties with tempo, as you can see by comparison with <a href="http://pragdave.pragprog.com/music/for_thee.mp3">the recording linked in his blog post</a>.</p>

<p></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fblog.purepistos.net%2Findex.php%2F2008%2F09%2F12%2Fthomas-for-thee%2F&amp;linkname=Thomas%20%26%238211%3B%20For%20Thee"><img src="http://blog.purepistos.net/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share/Bookmark"/></a>

<p>Related posts:<ol><li><a href='http://blog.purepistos.net/index.php/2009/10/16/chopin-nocturne-op-72-no-1-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Nocturne Op. 72, No. 1 in E minor'>Chopin &#8211; Nocturne Op. 72, No. 1 in E minor</a></li>
<li><a href='http://blog.purepistos.net/index.php/2009/12/21/chopin-prelude-op-28-no-4-in-e-minor/' rel='bookmark' title='Permanent Link: Chopin &#8211; Prelude Op. 28, No. 4 in E minor'>Chopin &#8211; Prelude Op. 28, No. 4 in E minor</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://blog.purepistos.net/index.php/2008/09/12/thomas-for-thee/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
<enclosure url="http://pragdave.pragprog.com/music/for_thee.mp3" length="4342076" type="audio/mpeg" />
		<enclosure url="http://blog.purepistos.net/wp-content/uploads/recordings/thomas/pistos--thomas-for-thee.mp3" length="2088960" type="audio/mpeg"/>
<itunes:duration>2:11</itunes:duration>
		<itunes:subtitle></itunes:subtitle>
		<itunes:summary></itunes:summary>
		<itunes:keywords></itunes:keywords>
		<itunes:author></itunes:author>
		<itunes:explicit>no</itunes:explicit>
		<itunes:block>No</itunes:block>
	</item>
	</channel>
</rss>
