<?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/"
	>

<channel>
	<title>Meta Bates &#187; Tutorials</title>
	<atom:link href="http://www.metabates.com/category/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.metabates.com</link>
	<description>The technical ramblings of Mark Bates.</description>
	<lastBuildDate>Wed, 01 Feb 2012 16:25:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Using Sprockets without Rails</title>
		<link>http://www.metabates.com/2011/08/31/using-sprockets-without-rails/</link>
		<comments>http://www.metabates.com/2011/08/31/using-sprockets-without-rails/#comments</comments>
		<pubDate>Wed, 31 Aug 2011 19:17:23 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[book]]></category>
		<category><![CDATA[coffee script]]></category>
		<category><![CDATA[coffeescript]]></category>
		<category><![CDATA[rack]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[sprockets]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=503</guid>
		<description><![CDATA[I&#8217;ve started working this week on an example application for the next book I&#8217;m about to write and I wanted a simple way for my readers to easily run the app (it&#8217;s going to be a single HTML file with a ton of cool JavaScript going on in it). My first choice for running this [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve started working this week on an example application for the next book I&#8217;m about to write and I wanted a simple way for my readers to easily run the app (it&#8217;s going to be a single HTML file with a ton of cool JavaScript going on in it). My first choice for running this app was to use the popular Ruby library, <a href="http://rack.rubyforge.org/" target="_blank">Rack</a>. If you are unfamiliar with Rack, please check it out. It provides a simple interface for writing web applications. By writing a simple Ruby file readers can use their favorite Rack compatible web server to launch the application. Sounds simple, eh? That&#8217;s because it is.</p>
<p>With a simple Rack application written in a few lines of code I was able to start developing my example application. That&#8217;s when I realized I needed a good way to serve up all my <a href="http://jashkenas.github.com/coffee-script/" target="_blank">CoffeeScript</a> and <a href="http://sass-lang.com/" target="_blank">Sass</a> files. I was going to write a watchr script that did this, but I thought that was a bit heavy handed, and not very flexible, so I turned to <a href="https://github.com/sstephenson/sprockets" target="_blank">Sprockets</a>.</p>
<p>Sprockets recently gained a lot of attention because it is bundled in with <a href="http://guides.rubyonrails.org/3_1_release_notes.html" target="_blank">Rails 3.1</a> to serve up an application&#8217;s assets. It&#8217;s a clever little library that will process your files using CoffeeScript, Sass, etc&#8230; and let you bundle them up in to a single asset by using a manifest. That was exactly what I wanted. After I spent the better part of an afternoon doing a bit of research and debugging here is the Rack configuration file I came up with:</p>
<div id="gist-1184400" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nb">require</span> <span class="s1">&#39;sprockets&#39;</span></div><div class='line' id='LC2'><span class="n">project_root</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">expand_path</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="bp">__FILE__</span><span class="p">))</span></div><div class='line' id='LC3'><span class="n">assets</span> <span class="o">=</span> <span class="no">Sprockets</span><span class="o">::</span><span class="no">Environment</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">project_root</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">env</span><span class="o">|</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="n">env</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="no">Logger</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span></div><div class='line' id='LC5'><span class="k">end</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="n">assets</span><span class="o">.</span><span class="n">append_path</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">project_root</span><span class="p">,</span> <span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="s1">&#39;assets&#39;</span><span class="p">))</span></div><div class='line' id='LC8'><span class="n">assets</span><span class="o">.</span><span class="n">append_path</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">project_root</span><span class="p">,</span> <span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="s1">&#39;assets&#39;</span><span class="p">,</span> <span class="s1">&#39;javascripts&#39;</span><span class="p">))</span></div><div class='line' id='LC9'><span class="n">assets</span><span class="o">.</span><span class="n">append_path</span><span class="p">(</span><span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">project_root</span><span class="p">,</span> <span class="s1">&#39;app&#39;</span><span class="p">,</span> <span class="s1">&#39;assets&#39;</span><span class="p">,</span> <span class="s1">&#39;stylesheets&#39;</span><span class="p">))</span></div><div class='line' id='LC10'><br/></div><div class='line' id='LC11'><span class="n">map</span> <span class="s2">&quot;/assets&quot;</span> <span class="k">do</span></div><div class='line' id='LC12'>&nbsp;&nbsp;<span class="n">run</span> <span class="n">assets</span></div><div class='line' id='LC13'><span class="k">end</span></div><div class='line' id='LC14'><br/></div><div class='line' id='LC15'><span class="n">map</span> <span class="s2">&quot;/&quot;</span> <span class="k">do</span></div><div class='line' id='LC16'>&nbsp;&nbsp;<span class="n">run</span> <span class="nb">lambda</span> <span class="p">{</span> <span class="o">|</span><span class="n">env</span><span class="o">|</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">[</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="mi">200</span><span class="p">,</span> </div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">{</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;Content-Type&#39;</span>  <span class="o">=&gt;</span> <span class="s1">&#39;text/html&#39;</span><span class="p">,</span> </div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="s1">&#39;Cache-Control&#39;</span> <span class="o">=&gt;</span> <span class="s1">&#39;public, max-age=86400&#39;</span> </div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">},</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">File</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s1">&#39;public/index.html&#39;</span><span class="p">,</span> <span class="no">File</span><span class="o">::</span><span class="no">RDONLY</span><span class="p">)</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="o">]</span></div><div class='line' id='LC25'>&nbsp;&nbsp;<span class="p">}</span></div><div class='line' id='LC26'><span class="k">end</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1184400/525bacf6830e9f5ae339b9f2f60814d146d7e529/config.ru" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1184400#file_config.ru" style="float:right;margin-right:10px;color:#666">config.ru</a>
            <a href="https://gist.github.com/1184400">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>That will serve</p>
<pre>/assets/application.css</pre>
<p>via Sprockets. The file itself will live in</p>
<pre>&lt;pwd&gt;/app/assets/stylesheets/application.scss</pre>
<p>The same goes for JavaScript files.</p>
<p>Hopefully this will save someone else a little of time when they&#8217;re trying to do the same thing. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2011/08/31/using-sprockets-without-rails/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building Interfaces and Abstract Classes in Ruby</title>
		<link>http://www.metabates.com/2011/02/07/building-interfaces-and-abstract-classes-in-ruby/</link>
		<comments>http://www.metabates.com/2011/02/07/building-interfaces-and-abstract-classes-in-ruby/#comments</comments>
		<pubDate>Mon, 07 Feb 2011 20:45:05 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.metabates.com/?p=393</guid>
		<description><![CDATA[So back in the dark ages of my career, pre-2006, I spent a long time coding Java. Yeah, I know, please don&#8217;t judge. Anyway, In Java, for those of you who are unaware were two constructs that I occasionally wish I had in Ruby, those are Interfaces and Abstract Classes. The difference between these two [...]]]></description>
			<content:encoded><![CDATA[<p>So back in the dark ages of my career, pre-2006, I spent a long time coding Java. Yeah, I know, please don&#8217;t judge. Anyway, In Java, for those of you who are unaware were two constructs that I occasionally wish I had in Ruby, those are <a href="http://download.oracle.com/javase/tutorial/java/concepts/interface.html" target="_blank">Interfaces</a> and <a href="http://download.oracle.com/javase/tutorial/java/IandI/abstract.html" target="_blank">Abstract Classes</a>. The difference between these two constructs is subtle, but important.</p>
<p>In Java an Interface is a basically a blueprint of methods that the class who implements the Interface needs to implement. For example:</p>
<div id="gist-814920" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kd">interface</span> <span class="nc">Bicycle</span> <span class="o">{</span></div><div class='line' id='LC2'><br/></div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="kt">void</span> <span class="nf">changeGear</span><span class="o">(</span><span class="kt">int</span> <span class="n">newValue</span><span class="o">);</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="kt">void</span> <span class="nf">speedUp</span><span class="o">(</span><span class="kt">int</span> <span class="n">increment</span><span class="o">);</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="kt">void</span> <span class="nf">applyBrakes</span><span class="o">(</span><span class="kt">int</span> <span class="n">decrement</span><span class="o">);</span></div><div class='line' id='LC8'><span class="o">}</span></div><div class='line' id='LC9'><br/></div><div class='line' id='LC10'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ACMEBicycle</span> <span class="kd">implements</span> <span class="n">Bicycle</span> <span class="o">{</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;<span class="kd">public</span> <span class="kt">void</span> <span class="nf">changeGear</span><span class="o">(</span><span class="kt">int</span> <span class="n">newValue</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// do some work here</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;<span class="kd">public</span> <span class="kt">void</span> <span class="nf">speedUp</span><span class="o">(</span><span class="kt">int</span> <span class="n">increment</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// do some work here</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;<span class="kd">public</span> <span class="kt">void</span> <span class="nf">applyBrakes</span><span class="o">(</span><span class="kt">int</span> <span class="n">decrement</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// do some work here</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC23'><br/></div><div class='line' id='LC24'><span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/814920/33db62faa407878926d6c84e03759ad77923053a/gistfile1.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/814920#file_gistfile1.java" style="float:right;margin-right:10px;color:#666">gistfile1.java</a>
            <a href="https://gist.github.com/814920">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>Here we have a <code>Bicycle</code> Interface that says there are three methods that need to be implemented. It is then the responsibility of the <code>ACMEBicycle</code> class to implement those methods. Now, an Abstract Class in Java is similar to an Interface in that it too is a blueprint of methods that the extending class may or may not need to implement. There in lies one of the differences between the two. Let&#8217;s take a look at the same example, but this time we want to implement the same behavior of all of our extending classes for the <code>applyBrakes</code> method:</p>
<div id="gist-814926" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">Bicycle</span> <span class="o">{</span></div><div class='line' id='LC2'>&nbsp;&nbsp;</div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="kd">abstract</span> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">changeGear</span><span class="o">(</span><span class="kt">int</span> <span class="n">newValue</span><span class="o">);</span></div><div class='line' id='LC4'><br/></div><div class='line' id='LC5'>&nbsp;&nbsp;<span class="kd">abstract</span> <span class="kd">public</span> <span class="kt">void</span> <span class="nf">speedUp</span><span class="o">(</span><span class="kt">int</span> <span class="n">increment</span><span class="o">);</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'>&nbsp;&nbsp;<span class="kd">public</span> <span class="kt">void</span> <span class="nf">applyBrakes</span><span class="o">(</span><span class="kt">int</span> <span class="n">decrement</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// do some work here</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC10'>&nbsp;&nbsp;</div><div class='line' id='LC11'><span class="o">}</span></div><div class='line' id='LC12'><br/></div><div class='line' id='LC13'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">ACMEBicycle</span> <span class="kd">extends</span> <span class="n">Bicycle</span> <span class="o">{</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;<span class="kd">public</span> <span class="kt">void</span> <span class="nf">applyBrakes</span><span class="o">(</span><span class="kt">int</span> <span class="n">decrement</span><span class="o">)</span> <span class="o">{</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1">// do some work here</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;<span class="o">}</span></div><div class='line' id='LC18'><br/></div><div class='line' id='LC19'><span class="o">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/814926/378f523b40a1dc33ae616ee6ffc58e3b32cc5b23/gistfile1.java" style="float:right;">view raw</a>
            <a href="https://gist.github.com/814926#file_gistfile1.java" style="float:right;margin-right:10px;color:#666">gistfile1.java</a>
            <a href="https://gist.github.com/814926">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>An Abstract Class is a great way to provide a mix of fully implemented methods as well as providing subclasses with a mixture of methods that need to be implemented by the extending class.</p>
<p>The really powerful part of all of this is two fold. First, the Java compiler will happily yell at you and fail if it finds that you haven&#8217;t implemented some of the methods that you were told you had to. Second, you can easily see the methods that you need to document right there, you can even copy/paste their definitions right into your class so you can start to fill them out.</p>
<p>So, how does this bring us over to Ruby? Great question. I&#8217;d like to take a few moments and explore a few ways we can get some of this power in Ruby.</p>
<p>Unfortunately, or fortunately depending on how you look at it (I see it as a mixed blessing), there is no compiler in Ruby, so we don&#8217;t really have a good way of having the system yell at us if we don&#8217;t implement the methods we were supposed to. But, there is still plenty we can do to help those who are implementing our classes both know what they need to implement and to find out what they haven&#8217;t implemented when their program is executing.</p>
<p>Here is one implementation on we can gain a bit of that functionality back in Ruby:</p>
<div id="gist-815110" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">module</span> <span class="nn">AbstractInterface</span></div><div class='line' id='LC2'>&nbsp;&nbsp;</div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">class</span> <span class="nc">InterfaceNotImplementedError</span> <span class="o">&lt;</span> <span class="no">NoMethodError</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC5'>&nbsp;&nbsp;</div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">included</span><span class="p">(</span><span class="n">klass</span><span class="p">)</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">klass</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:include</span><span class="p">,</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">Methods</span><span class="p">)</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">klass</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:extend</span><span class="p">,</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">Methods</span><span class="p">)</span></div><div class='line' id='LC9'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC10'>&nbsp;&nbsp;</div><div class='line' id='LC11'>&nbsp;&nbsp;<span class="k">module</span> <span class="nn">Methods</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">api_not_implemented</span><span class="p">(</span><span class="n">klass</span><span class="p">)</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">caller</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/in \`(.+)\&#39;/</span><span class="p">)</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">method_name</span> <span class="o">=</span> <span class="vg">$1</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">raise</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">InterfaceNotImplementedError</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="n">klass</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> needs to implement &#39;</span><span class="si">#{</span><span class="n">method_name</span><span class="si">}</span><span class="s2">&#39; for interface </span><span class="si">#{</span><span class="nb">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">!&quot;</span><span class="p">)</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC19'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC20'>&nbsp;&nbsp;</div><div class='line' id='LC21'><span class="k">end</span></div><div class='line' id='LC22'><br/></div><div class='line' id='LC23'><span class="k">class</span> <span class="nc">Bicycle</span></div><div class='line' id='LC24'>&nbsp;&nbsp;<span class="kp">include</span> <span class="no">AbstractInterface</span></div><div class='line' id='LC25'>&nbsp;&nbsp;</div><div class='line' id='LC26'>&nbsp;&nbsp;<span class="c1"># Some documentation on the change_gear method</span></div><div class='line' id='LC27'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">change_gear</span><span class="p">(</span><span class="n">new_value</span><span class="p">)</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">Bicycle</span><span class="o">.</span><span class="n">api_not_implemented</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span></div><div class='line' id='LC29'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC30'>&nbsp;&nbsp;</div><div class='line' id='LC31'>&nbsp;&nbsp;<span class="c1"># Some documentation on the speed_up method</span></div><div class='line' id='LC32'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">speed_up</span><span class="p">(</span><span class="n">increment</span><span class="p">)</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">Bicycle</span><span class="o">.</span><span class="n">api_not_implemented</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span></div><div class='line' id='LC34'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC35'>&nbsp;&nbsp;</div><div class='line' id='LC36'>&nbsp;&nbsp;<span class="c1"># Some documentation on the apply_brakes method</span></div><div class='line' id='LC37'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">apply_brakes</span><span class="p">(</span><span class="n">decrement</span><span class="p">)</span></div><div class='line' id='LC38'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1"># do some work here</span></div><div class='line' id='LC39'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC40'>&nbsp;&nbsp;</div><div class='line' id='LC41'><span class="k">end</span></div><div class='line' id='LC42'><br/></div><div class='line' id='LC43'><span class="k">class</span> <span class="nc">AcmeBicycle</span> <span class="o">&lt;</span> <span class="no">Bicycle</span></div><div class='line' id='LC44'><span class="k">end</span></div><div class='line' id='LC45'><br/></div><div class='line' id='LC46'><span class="n">bike</span> <span class="o">=</span> <span class="no">AcmeBicycle</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC47'><span class="n">bike</span><span class="o">.</span><span class="n">change_gear</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># AbstractInterface::InterfaceNotImplementedError: AcmeBicycle needs to implement &#39;change_gear&#39; for interface Bicycle!</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/815110/86499cb60e04a53989d06d3763c44ff3d9a99984/gistfile1.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/815110#file_gistfile1.rb" style="float:right;margin-right:10px;color:#666">gistfile1.rb</a>
            <a href="https://gist.github.com/815110">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>What we&#8217;ve done here is to inject a Module into our <code>Bicycle</code> class to give it a nice error it can raise and a little bit of help building a nice error message for the user. Then in our <code>Bicycle</code> class we define all the methods we want and in the ones we need the end user to define we can call the <code>api_not_implemented</code> method and it will raise the <code>AbstractInterface::InterfaceNotImplementedError</code> error for us.</p>
<p>We could simplify this a bit by having a nice little helper macro that we can use to build these methods, like this:</p>
<div id="gist-815133" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="k">module</span> <span class="nn">AbstractInterface</span></div><div class='line' id='LC2'>&nbsp;&nbsp;</div><div class='line' id='LC3'>&nbsp;&nbsp;<span class="k">class</span> <span class="nc">InterfaceNotImplementedError</span> <span class="o">&lt;</span> <span class="no">NoMethodError</span></div><div class='line' id='LC4'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC5'>&nbsp;&nbsp;</div><div class='line' id='LC6'>&nbsp;&nbsp;<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">included</span><span class="p">(</span><span class="n">klass</span><span class="p">)</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">klass</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:include</span><span class="p">,</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">Methods</span><span class="p">)</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">klass</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:extend</span><span class="p">,</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">Methods</span><span class="p">)</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">klass</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="ss">:extend</span><span class="p">,</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">ClassMethods</span><span class="p">)</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC11'>&nbsp;&nbsp;</div><div class='line' id='LC12'>&nbsp;&nbsp;<span class="k">module</span> <span class="nn">Methods</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">api_not_implemented</span><span class="p">(</span><span class="n">klass</span><span class="p">,</span> <span class="n">method_name</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span></div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">method_name</span><span class="o">.</span><span class="n">nil?</span></div><div class='line' id='LC16'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">caller</span><span class="o">.</span><span class="n">first</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sr">/in \`(.+)\&#39;/</span><span class="p">)</span></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">method_name</span> <span class="o">=</span> <span class="vg">$1</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">raise</span> <span class="no">AbstractInterface</span><span class="o">::</span><span class="no">InterfaceNotImplementedError</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&quot;</span><span class="si">#{</span><span class="n">klass</span><span class="o">.</span><span class="n">class</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2"> needs to implement &#39;</span><span class="si">#{</span><span class="n">method_name</span><span class="si">}</span><span class="s2">&#39; for interface </span><span class="si">#{</span><span class="nb">self</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">!&quot;</span><span class="p">)</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC22'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC23'>&nbsp;&nbsp;</div><div class='line' id='LC24'>&nbsp;&nbsp;<span class="k">module</span> <span class="nn">ClassMethods</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">def</span> <span class="nf">needs_implementation</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">self</span><span class="o">.</span><span class="n">class_eval</span> <span class="k">do</span></div><div class='line' id='LC28'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">define_method</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span> <span class="k">do</span> <span class="o">|*</span><span class="n">args</span><span class="o">|</span></div><div class='line' id='LC29'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="no">Bicycle</span><span class="o">.</span><span class="n">api_not_implemented</span><span class="p">(</span><span class="nb">self</span><span class="p">,</span> <span class="nb">name</span><span class="p">)</span></div><div class='line' id='LC30'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC31'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC32'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC33'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC34'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC35'>&nbsp;&nbsp;</div><div class='line' id='LC36'><span class="k">end</span></div><div class='line' id='LC37'><br/></div><div class='line' id='LC38'><span class="k">class</span> <span class="nc">Bicycle</span></div><div class='line' id='LC39'>&nbsp;&nbsp;<span class="kp">include</span> <span class="no">AbstractInterface</span></div><div class='line' id='LC40'>&nbsp;&nbsp;</div><div class='line' id='LC41'>&nbsp;&nbsp;<span class="n">needs_implementation</span> <span class="ss">:change_gear</span><span class="p">,</span> <span class="ss">:new_value</span></div><div class='line' id='LC42'>&nbsp;&nbsp;<span class="n">needs_implementation</span> <span class="ss">:speed_up</span><span class="p">,</span> <span class="ss">:increment</span></div><div class='line' id='LC43'>&nbsp;&nbsp;</div><div class='line' id='LC44'>&nbsp;&nbsp;<span class="c1"># Some documentation on the apply_brakes method</span></div><div class='line' id='LC45'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">apply_brakes</span><span class="p">(</span><span class="n">decrement</span><span class="p">)</span></div><div class='line' id='LC46'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="c1"># do some work here</span></div><div class='line' id='LC47'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC48'>&nbsp;&nbsp;</div><div class='line' id='LC49'><span class="k">end</span></div><div class='line' id='LC50'><br/></div><div class='line' id='LC51'><span class="k">class</span> <span class="nc">AcmeBicycle</span> <span class="o">&lt;</span> <span class="no">Bicycle</span></div><div class='line' id='LC52'><span class="k">end</span></div><div class='line' id='LC53'><br/></div><div class='line' id='LC54'><span class="n">bike</span> <span class="o">=</span> <span class="no">AcmeBicycle</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC55'><span class="n">bike</span><span class="o">.</span><span class="n">change_gear</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># AbstractInterface::InterfaceNotImplementedError: AcmeBicycle needs to implement &#39;change_gear&#39; for interface Bicycle!</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/815133/aacc6defab9cfa8801a042ab386daf27685e3981/gistfile1.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/815133#file_gistfile1.rb" style="float:right;margin-right:10px;color:#666">gistfile1.rb</a>
            <a href="https://gist.github.com/815133">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>That approach certainly makes our code look a bit cleaner, I&#8217;m not denying that, however it has one really big flaw, at least for me anyway, it doesn&#8217;t give us a good to place to hang our documentation hat. In the previous approach we had actual methods that we could then document and that documentation would then show up in RDoc when it&#8217;s outputted. With the latter approach, however, we can document the hell out of the <code>needs_implementation</code> calls we have in the <code>Bicycle</code> class, but they won&#8217;t ever show up in the documentation. That means that users of our library have to crack open the actual code itself to see what it they are expected to implement.</p>
<p>Another approach we could&#8217;ve taken, which I bother to demonstrate here as I don&#8217;t think it offers a better approach is to have the <code>needs_implementation</code> method collect up the names of those methods and use <code>method_missing</code> to report that the method needs to be implemented. I mention it here only for completeness, but it definitely is not the best solution to this problem.</p>
<p>Finally, I would like to note that, as far as I can see, there is no way in Ruby to create a callback hook for when a class has been defined. If there was in fact such a hook we could use to it immediately notify the end user that they have forgotten to implement certain methods. Perhaps in Ruby 2.0??? That&#8217;s just pure hope on my part.</p>
<p>That&#8217;s it. I hope you enjoyed our brief (*cough*) look through implementing Interface and Abstract Classes in Ruby. I hope you&#8217;ve enjoyed it.</p>
<p>* PS, yes, I&#8217;m aware I didn&#8217;t talk about multiple vs. single inheritance in either Java or Ruby, nor did I talk about the fact that in Ruby you can&#8217;t really have Abstract Classes. I thought that was all a bit much for an already rather lengthy post as it was. Perhaps another day. <img src='http://www.metabates.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2011/02/07/building-interfaces-and-abstract-classes-in-ruby/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>How to use a non-singleton version of Configatron</title>
		<link>http://www.metabates.com/2008/11/20/how-to-use-a-non-singleton-version-of-configatron/</link>
		<comments>http://www.metabates.com/2008/11/20/how-to-use-a-non-singleton-version-of-configatron/#comments</comments>
		<pubDate>Thu, 20 Nov 2008 12:20:24 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[configatron]]></category>
		<category><![CDATA[singleton]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=198</guid>
		<description><![CDATA[Since Configatron has come out it&#8217;s become a pretty popular library, and because of that I&#8217;ve received several feature requests. Nothing wrong with that. I actually welcome that, because, let&#8217;s be honest, that&#8217;s how configatron will become even better. The biggest request I&#8217;ve received is from people who want to use Configatron, but they want [...]]]></description>
			<content:encoded><![CDATA[<p>Since Configatron has come out it&#8217;s become a pretty popular library, and because of that I&#8217;ve received several feature requests. Nothing wrong with that. I actually welcome that, because, let&#8217;s be honest, that&#8217;s how configatron will become even better.</p>
<p>The biggest request I&#8217;ve received is from people who want to use Configatron, but they want their own instance of it, and not the global singleton instance of it. Although, I personally don&#8217;t see why you would need that, I&#8217;m a big enough man to understand that just because I don&#8217;t need it, doesn&#8217;t mean others don&#8217;t.</p>
<p>Last night I was reviewing the code, because I was asked this question again, and in doing so I realized that power has been there all along. It&#8217;s actually very simple. When you make a call on <code>Kernel#configatron</code> it returns a singleton of the <code>Configatron</code> class, but after that all it does is return an instance of the <code>Configatron::Store</code> class. So if you want your own instance of Configatron, what you really want is an instance of the <code>Configatron::Store</code> class, which you can do like so:</p>
<p><script src="http://gist.github.com/27027.js"></script>Â </p>
<p>Well, there you go, I hope that helps. Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/11/20/how-to-use-a-non-singleton-version-of-configatron/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preview (0.7.0): Building Distributed Application w/ Mack (Screencast!)</title>
		<link>http://www.metabates.com/2008/08/18/preview-070-building-distributed-application-w-mack-screencast/</link>
		<comments>http://www.metabates.com/2008/08/18/preview-070-building-distributed-application-w-mack-screencast/#comments</comments>
		<pubDate>Tue, 19 Aug 2008 04:06:17 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[News]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[0.7.0]]></category>
		<category><![CDATA[distributed objects]]></category>
		<category><![CDATA[distributed routes]]></category>
		<category><![CDATA[distributed views/layouts]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[screencast]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=133</guid>
		<description><![CDATA[On Monday, August 25th, Mack 0.7.0 will be released. This is an extremely important release for Mack. Why is that you ask? Good question. Well, this is release that finally brings the much talked about distributed feature set to Mack. Distributed routes have been around for quite some time, but distributed views/layouts and distributed objects [...]]]></description>
			<content:encoded><![CDATA[<p>On Monday, August 25th, Mack 0.7.0 will be released. This is an extremely important release for Mack. Why is that you ask? Good question. Well, this is release that finally brings the much talked about distributed feature set to Mack. Distributed routes have been around for quite some time, but distributed views/layouts and distributed objects (models) have been missing. Well, in less than a week, you&#8217;ll have them!</p>
<p>Now I know that you&#8217;re just as excited about what&#8217;s coming as I am, that&#8217;s why I&#8217;ve prepared the first ever Mack screencast to demostrate these features. The screencast is a little rough around the edges, but it gets the ideas across.Â </p>
<p>As always I&#8217;ll post more about the 0.7.0 as the release date nears. In the meantime enjoy the screencast:</p>
<p><a href="http://screencasts.mackframework.com/Mack%20Distributed%20Demo.mov">The Mack Distributed Demo Screencast</a></p>
<p>Here&#8217;s the <a href="http://screencasts.mackframework.com/distributed_demo_source.zip" target="_blank">source</a> code.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/08/18/preview-070-building-distributed-application-w-mack-screencast/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
<enclosure url="http://screencasts.mackframework.com/Mack%20Distributed%20Demo.mov" length="71916306" type="video/quicktime" />
		</item>
		<item>
		<title>Preview (0.5.5): Adding PDF::Writer Plugin Support Tutorial</title>
		<link>http://www.metabates.com/2008/05/20/055-adding-pdfwriter-plugin-support-tutorial/</link>
		<comments>http://www.metabates.com/2008/05/20/055-adding-pdfwriter-plugin-support-tutorial/#comments</comments>
		<pubDate>Tue, 20 May 2008 20:45:27 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[engine]]></category>
		<category><![CDATA[erubis]]></category>
		<category><![CDATA[gems]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[render]]></category>
		<category><![CDATA[rendering]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=99</guid>
		<description><![CDATA[Ok, let&#8217;s take the new rendering system out for a spin, shall we? Let&#8217;s add the PDF::Writer library to our Obligatory Blog Demo application. If you haven&#8217;t followed this demo you should do that now. Let&#8217;s start by requiring the gem in our system. Open up your gems.rb file found in config/initializers and let&#8217;s add [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, let&#8217;s take the new rendering system out for a spin, shall we? Let&#8217;s add the PDF::Writer library to our Obligatory Blog Demo application. If you haven&#8217;t followed this demo you should do that <a href="http://www.mackframework.com/2008/04/18/046-the-obligatory-blog-demo-take-2/" target="_blank">now</a>.</p>
<p>Let&#8217;s start by requiring the gem in our system. Open up your gems.rb file found in config/initializers and let&#8217;s add the gem:</p>
<pre>require_gems do |gem|
  gem.add "pdf-writer", :version =&gt; "1.1.8", :libs =&gt; "pdf/writer"
end</pre>
<p>Great! We&#8217;ve told Mack we want to use the &#8216;pdf-writer&#8217; gem, version &#8217;1.1.8&#8242;, and we want to automatically require the file &#8216;pdf/writer&#8217;. Now, let&#8217;s install the gem:</p>
<pre>$ sudo rake gems:install</pre>
<p>See how easy this is? We&#8217;ve installed the gem, required the libraries, now we&#8217;re ready to write our plugin.</p>
<pre>$ rake generate:plugin name=render_pdf</pre>
<p>That should generate a few files/folders in our vendor/plugins directory. Let&#8217;s open up vendor/plugins/render_pdf/lib/render_pdf.rb and let&#8217;s start coding.</p>
<p>What we want to do is create a new Mack::Rendering::Engine::Base class so that when we call render(:action) it will have a new engine to render the view file as a PDF.</p>
<p>We&#8217;ll examine each section in a minute, but for now, let&#8217;s type this into our render_pdf.rb file:</p>
<pre>module Mack
  module Rendering
    module Engine
      class Pdf &lt; Mack::Rendering::Engine::Base

        def render(io, binding)
          @_pdf = ::PDF::Writer.new
          self.view_template.instance_variable_set("@_pdf", @_pdf)
          eval(io, binding)
          @_pdf.render
        end

        def extension
          :pdfw
        end

        module ViewHelpers
          def pdf
            @_pdf
          end
        end

      end
    end
  end
end
Mack::Rendering::ViewTemplate.send(:include, Mack::Rendering::Engine::Pdf::ViewHelpers)
Mack::Rendering::Engine::Registry.register(:action, :pdf)</pre>
<p>Ok, so on line #4 we extended Mack::Rendering::Engine::Base. This will give us access to a view methods, and will allow us to write to a very simple API. The only method you are <em>absolutely</em> required to implement is the render method. As we can see on line #6, we did just that.</p>
<p>First thing we do in the render method is instantiate a new PDF::Writer class and assign it to an instance variable. We then set that instance variable into the Mack::Rendering::ViewTemplate object we have. We do that because the way the PDF::Writer object works you need to constantly reference the instance of the writer to do your work. Example:</p>
<pre>@_pdf.text "Hello World", :font_size =&gt; 24, :justification =&gt; :center</pre>
<p>On line #9 we eval the io and the binding we&#8217;ve been given. The io will be contents of the view file we have disk, as a String, and the binding will be that of the Mack::Rendering::ViewTemplate object we&#8217;ve been given.</p>
<p>In the extension method we tell the system that are files are going to be found with the extension, pdfw. Another example of this would be the Erubis engine which declares its extension as erb.</p>
<p>The Mack::Rendering::Engine::Pdf::ViewHelpers module we&#8217;ve declared on line #17 is there to hide the @_pdf instance variable with a nicer pdf method. On line #27 we include this module into Mack::Rendering::ViewTemplate so it has access to it.</p>
<p>Finally, and most importantly, we need to register the new engine we&#8217;ve built with the system. We do that on line #28 with this bit of code:</p>
<pre>Mack::Rendering::Engine::Registry.register(:action, :pdf)</pre>
<p>That&#8217;s saying whenever someone calls render(:action), consider me as an engine to render that. The way the selection of which engine to use is done, is very simple. First come first serve. The engines are in an array, and the first one to have a file with its extension on disk wins. Plain and simple.</p>
<p>Now, let&#8217;s see all this in action. Let&#8217;s add PDF support for our &#8216;show&#8217; page.</p>
<p>Open up views/posts/show.html.erb and add the following line:</p>
<pre>&lt;%= link_to("pdf", posts_show_url(:id =&gt; @post, :format =&gt; :pdf)) %&gt;</pre>
<p>That will give us a link that looks like &#8216;/posts/:id.pdf&#8217;. This will, of course, go to our PostsController and the show action. This method does not need to be altered. That&#8217;s right, you heard me. It does not need to change. Mack will handle the appropriate content-type headers for you. Just another great feature in 0.5.5.</p>
<p>Create a file called views/posts/show.pdf.pdfw. I know this might look a little weird, what with &#8216;pdf.pdfw&#8217;, but here&#8217;s the reason why. That&#8217;s break the file name down into its three parts. &#8216;show&#8217; is the name of the action. &#8216;pdf&#8217; is the format of the request, think also html, xml, etc&#8230; &#8216;pdfw&#8217; is the engine we want to use. If we hated ourselves we could do this all in erb with a file called show.pdf.erb, but why would we want to do that?</p>
<p>Anyway, let&#8217;s dump this nice block of code into our show.pdf.pdfw file:</p>
<pre>pdf.select_font "Times-Roman"
pdf.fill_color(Color::RGB::Red)
pdf.text @post.title, :font_size =&gt; 24, :justification =&gt; :center
pdf.fill_color(Color::RGB::Black)
pdf.text "by #{@post.email}", :font_size =&gt; 12, :justification =&gt; :center
pdf.with_options(:font_size =&gt; 10, :justification =&gt; :left) do |p|
  p.text "\n\n"
  p.text @post.body
  p.text "\n\n"
  p.text "Created at: #{@post.created_at}"
  p.text "Updated at: #{@post.updated_at}"
end</pre>
<p>Since this is not a tutorial on this particular gem, I&#8217;m not going to go into what all that does. Instead, let&#8217;s just have a look at it in action.</p>
<p>Fire up your server:</p>
<pre>$ rake server</pre>
<p>And go to: http://localhost:3000. If you don&#8217;t already have a post created, create one. Now click on the show link. You should have a link on your page that says &#8216;pdf&#8217; click on that link. Voila! You should be seeing a wonderfully formatted PDF right now!</p>
<p>Congrats! You&#8217;ve built a plugin and a new rendering engine for Mack. Now, go crazy!</p>
<p>The source for all this can be found at:Â <a href="http://github.com/markbates/mack_blog_demo/tree/master" target="_blank">http://github.com/markbates/mack_blog_demo/tree/master</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/05/20/055-adding-pdfwriter-plugin-support-tutorial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>0.4.6: The Obligatory &#8216;Blog&#8217; Demo &#8211; Take 2</title>
		<link>http://www.metabates.com/2008/04/18/046-the-obligatory-blog-demo-take-2/</link>
		<comments>http://www.metabates.com/2008/04/18/046-the-obligatory-blog-demo-take-2/#comments</comments>
		<pubDate>Fri, 18 Apr 2008 22:12:04 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[data mapper]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[post]]></category>
		<category><![CDATA[scaffold]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/?p=60</guid>
		<description><![CDATA[This post has moved to the wiki @&#160;http://wiki.mackframework.com/index.php/Blog%20Tutorial]]></description>
			<content:encoded><![CDATA[<p>This post has moved to the wiki @&nbsp;<a href="http://wiki.mackframework.com/index.php/Blog%20Tutorial" target="_blank">http://wiki.mackframework.com/index.php/Blog%20Tutorial</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/04/18/046-the-obligatory-blog-demo-take-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>0.3.0: Adding RSS/xml feeds to our Blog demo</title>
		<link>http://www.metabates.com/2008/03/19/adding-rssxml-feeds-to-our-blog-demo/</link>
		<comments>http://www.metabates.com/2008/03/19/adding-rssxml-feeds-to-our-blog-demo/#comments</comments>
		<pubDate>Wed, 19 Mar 2008 20:42:49 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[builder]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[rss]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/2008/03/19/adding-rssxml-feeds-to-our-blog-demo/</guid>
		<description><![CDATA[Ok, as you remember a while back we created a simple blog using mack, http://www.mackframework.com/2008/03/04/the-obligatory-blog-demo/. Well now it&#8217;s time to add the all important RSS/xml feed to it. Mack 0.3.0 introduces xml rendering support natively, so this shouldn&#8217;t be so hard. First things first, let&#8217;s fire up the app, shall we: $ rake server Now [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, as you remember a while back we created a simple blog using mack, <a href="http://www.mackframework.com/2008/03/04/the-obligatory-blog-demo/" target="_blank">http://www.mackframework.com/2008/03/04/the-obligatory-blog-demo/</a>. Well now it&#8217;s time to add the all important RSS/xml feed to it.</p>
<p>Mack 0.3.0 introduces xml rendering support natively, so this shouldn&#8217;t be so hard. First things first, let&#8217;s fire up the app, shall we:</p>
<pre>$ rake server</pre>
<p>Now let&#8217;s head over to http://localhost:3000/posts. We should see our beautiful posts index page. Now let&#8217;s try to go to http://localhost:3000/posts.xml you should see something that looks like this:</p>
<p><img src="http://www.mackframework.com/wp-content/uploads/2008/03/xml1.png" alt="XML blog demo 1" width="450" /></p>
<p>Clearly, that&#8217;s not what we want, is it? I didn&#8217;t think so. The error is telling us that it&#8217;s looking for a file called index.xml.erb in the app/views/posts directory of our blog project. Obviously that file doesn&#8217;t exist.</p>
<p>Let&#8217;s take a second and talk about <em>why</em> Mack was looking for index.xml.erb. We haven&#8217;t changed anything in our controller. Our index method still looks something like this:</p>
<pre>def index
  @posts = Post.find(:all)
end</pre>
<p>No where in there does it mention xml. The only place xml is mentioned is on the the url itself, remember? We looked for /posts.xml. By adding .xml you&#8217;re telling Mack that you want to render, well&#8230; xml. So it goes looking for that. That&#8217;s also new in 0.3.0. The default is html, but if you append a format (.js, .xml, etc&#8230;), it will go looking for app/views/&lt;controller_name&gt;/&lt;action_name&gt;.&lt;format&gt;.erb and render it.</p>
<p>Ok, now that we understand why we&#8217;re looking for an xml file, let&#8217;s fire up our trusty text editor and create a new file called: app/views/posts/index.xml.erb. Let&#8217;s edit the file to look like this:</p>
<pre>xml.instruct! <img src='http://www.metabates.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml, :version=&gt;"1.0"
xml.rss(:version =&gt; "2.0") do
  xml.channel do
    xml.title("My Mack Blog")
    xml.link(posts_index_full_url)
    xml.description("Find out about all the cool stuff happening on my blog!")
    xml.language("en-us")
    xml.copyright("Copyright Me")
    xml.pubDate(CGI.rfc1123_date(Time.now))
    xml.lastBuildDate(CGI.rfc1123_date(Time.now))
    @posts.each do |post|
      xml.entry do
        xml.title(post.title)
        xml.link(posts_show_full_url(:id =&gt; post.id))
        xml.description(post.body)
        xml.pubDate(post.created_at.strftime("%a, %d %b %Y %H:%M:%S"))
      end
    end
  end
end</pre>
<p>Mack uses the standard builder gem library. I&#8217;m not going to go into explaining how that works, there are plenty of other tutorials and documentation that will show you that. I&#8217;m also not going to explain all the necessary pieces of an RSS feed. Instead I&#8217;ll point out in that code you&#8217;ll see we&#8217;re using the @posts instance variable that we set in the index action of our PostsController. Just like regular *.html.erb files we have access to all the instance variables from the controller, as well, helpers, etc&#8230;</p>
<p>So now if we go to http://localhost:3000/posts.xml we should see our RSS feed. If we did a view source we should see something that looks like this:</p>
<pre id="line1"><span class="pi">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
&lt;<span class="start-tag">rss</span><span class="attribute-name"> version</span>=<span class="attribute-value">"2.0"</span>&gt;
 &lt;<span class="start-tag">channel</span>&gt;
  &lt;<span class="start-tag">title</span>&gt;My Mack Blog&lt;/<span class="end-tag">title</span>&gt;
  &lt;<span class="start-tag">link</span>&gt;http://localhost:3000/posts&lt;/<span class="end-tag">link</span>&gt;
  &lt;<span class="start-tag">description</span>&gt;Find out about all the cool stuff happening on my blog!&lt;/<span class="end-tag">description</span>&gt;
  &lt;<span class="start-tag">language</span>&gt;en-us&lt;/<span class="end-tag">language</span>&gt;
  &lt;<span class="start-tag">copyright</span>&gt;Copyright Me&lt;/<span class="end-tag">copyright</span>&gt;</pre>
<pre id="line9">  &lt;<span class="start-tag">pubDate</span>&gt;Tue, 18 Mar 2008 17:18:05 GMT&lt;/<span class="end-tag">pubDate</span>&gt;
  &lt;<span class="start-tag">lastBuildDate</span>&gt;Tue, 18 Mar 2008 17:18:05 GMT&lt;/<span class="end-tag">lastBuildDate</span>&gt;
  &lt;<span class="start-tag">entry</span>&gt;
   &lt;<span class="start-tag">title</span>&gt;My New Post&lt;/<span class="end-tag">title</span>&gt;
   &lt;<span class="start-tag">link</span>&gt;http://localhost:3000/posts/1&lt;/<span class="end-tag">link</span>&gt;
   &lt;<span class="start-tag">description</span>&gt;This is my first post in my cool Mack blog!&lt;/<span class="end-tag">description</span>&gt;</pre>
<pre id="line15">   &lt;<span class="start-tag">pubDate</span>&gt;Tue, 18 Mar 2008 11:58:30&lt;/<span class="end-tag">pubDate</span>&gt;
  &lt;/<span class="end-tag">entry</span>&gt;
 &lt;/<span class="end-tag">channel</span>&gt;
&lt;/<span class="end-tag">rss</span>&gt;</pre>
<p>Awesome! All that&#8217;s really left is create one of those fancy RSS tags in the location field of our browsers that people can click and go straight to the RSS feed. Let&#8217;s do that now.</p>
<p>At the top of your app/views/posts/index.html.erb file add the following:</p>
<pre>&lt;%= rss_tag(posts_index_url(:format =&gt; <img src='http://www.metabates.com/wp-includes/images/smilies/icon_mad.gif' alt=':x' class='wp-smiley' /> ml)) %&gt;</pre>
<p>Now, refresh the page in your browser, and there you go, you should now see the little RSS button in the location bar of your browser. If you click that you should be taken to your feed.</p>
<p>That&#8217;s all there is to adding not only xml, but an RSS feed to your new blog.</p>
<p>The code for this demo can be found <a href="http://www.mackframework.com/wp-content/uploads/2008/03/mack_blog_demo.zip" title="Blog Demo w/ XML">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/03/19/adding-rssxml-feeds-to-our-blog-demo/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>&#8216;Helpers&#8217; in Mack</title>
		<link>http://www.metabates.com/2008/03/18/helpers-in-mack/</link>
		<comments>http://www.metabates.com/2008/03/18/helpers-in-mack/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 15:36:15 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[application helper]]></category>
		<category><![CDATA[helpers]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[modules]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rdoc]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/2008/03/18/helpers-in-mack/</guid>
		<description><![CDATA[Let&#8217;s talk a bit about &#8216;helpers&#8217; in Mack, shall we? How does Rails handle helpers? Those ofÂ  you familiar with Rails are already familiar with this concepts. In Rails helpers are modules of code that get included into views for certain controllers, or all controllers in the case of ApplicationHelper. These helpers are meant to [...]]]></description>
			<content:encoded><![CDATA[<p>Let&#8217;s talk a bit about &#8216;helpers&#8217; in Mack, shall we?</p>
<h2>How does Rails handle helpers?</h2>
<p>Those ofÂ  you familiar with Rails are already familiar with this concepts. In Rails helpers are modules of code that get included into views for certain controllers, or all controllers in the case of ApplicationHelper. These helpers are meant to clean up the views and encapsulate commonly used Ruby code and keep it out of the views. In Rails 2.0 it&#8217;s easier now to include some of these helper methods into the controller, but by default, they&#8217;re not readily available.</p>
<h2>How does Mack handle helpers?</h2>
<p>Mack deals with helpers a little differently. Let&#8217;s start with ApplicationHelper. In Rails, ApplicationHelper gets included into all the views for every controller. This is extremely useful, and from my experience it&#8217;s the most used helper in Rails. The same is true of Mack. Regardless of which controller/view you&#8217;re in, ApplicationHelper is there to assist. This brings us to our first difference between Rails and Mack:</p>
<p><strong>* ApplicationHelper is included into both the views AND the controllers.</strong></p>
<p>That&#8217;s right, you no longer have to do special voodoo magic to get the contents of ApplicationHelper included into your controller, it&#8217;s right there by default, ready to go. Now, I know at this stage you&#8217;re saying, if ApplicationHelper is included into all controllers, as well as views, then aren&#8217;t the methods in there publicly accessible as actions? The answer is no. Which brings us to our next point on helpers:</p>
<p><strong>* All helper public helper methods are converted to protected methods prior to be included into controllers/views.</strong></p>
<p>By converting all public methods in helpers to protected methods we get around the security concerns regarding the methods becoming publicly available actions in the controllers.</p>
<p>Now, in Rails when you create a controller it creates a new helper module file for that controller. The idea being that you can put helpers into this module that are only available to that controller&#8217;s views.</p>
<p><strong>* Mack helpers are NOT controller specific.</strong></p>
<p>Mack, doesn&#8217;t do what Rails does in this respect. It&#8217;s been my personal experience that these files end up empty and just take up space on my disk. So screw em! We don&#8217;t need em.</p>
<h2>Mack only helper concepts</h2>
<p>Ok, so we&#8217;ve covered the basics of helpers, let&#8217;s talk about a couple of concepts that are available only in the Mack world.</p>
<h3>Controller Helpers:</h3>
<p>What are controller helpers? In my experience working with Rails I found that I would have &#8216;helper&#8217; methods, protected or private of course, in my controllers that were meant to assist the actual actions in that controller. Two things eventually dawned on me. The first was that I&#8217;m cluttering up my controllers with all these helper methods. The second was that there should be a way to share these amongst other controllers that could probably use them as well. (Example, methods dealing with authentication)</p>
<p>In the Rails world I wrote a gem, controller_helpers, that helps to facilitate this. Well, being as this is the Mack world, this facility is built right in.</p>
<p>If you go and create a module in the app/helpers folder that&#8217;s follows the naming convention &lt;controller_name&gt;Helper then it will automatically be included into the appropriate controller. Two things to note here, the security model is still applied, public methods become protected methods. The second is these methods are available in that controller ONLY. They are not available in other controllers or any views within that controller.</p>
<pre>class BlogController &lt; Mack::Controller::Base
  before_filter :authenticate
end</pre>
<pre>module BlogControllerHelper
  def authenticate
    # do work to authenticate user here...
  end
end</pre>
<p>As we see the controller name in the previous example was BlogController and it&#8217;s helper name was BlogControllerHelper. Now in the example we had an authenticate method in BlogControllerHelper, we realize that we also want to use that in our CommentsController as well. So we can refactor that example to look like this:</p>
<pre>class BlogController &lt; Mack::Controller::Base
  before_filter :authenticate
end

class CommentsController &lt; Mack::Controller::Base
  before_filter :authenticate
end</pre>
<pre>module AuthenticationControllerHelper
  def authenticate
    # do work to authenticate user here...
  end
  include_safely_into(BlogController, CommentsController)
end</pre>
<p>Here you can see in our new AuthenticationControllerHelper module we use the include_safely_into method. This method is documented in the RDoc for Mack, but basically what it does is includes that module into the list of Classes defined, and changes it&#8217;s public methods to protected.</p>
<p>Now we have included controller helpers into several different controllers. This helps to keep our controllers limited to just actions, and helps us to reuse code in other places. All very good things.</p>
<h3>Refactoring ApplicationHelper</h3>
<p>So, if you&#8217;re like me, your Rails ApplicationHelper module is absolutely overflowing with all sorts of bits of code. In one project I have it&#8217;s 682 lines of code! Some code does authentication like stuff, is_logged_in?, is_logged_out?, etc&#8230; some does formatting, some does other stuff. It&#8217;s a big steaming pile of unrelated code.</p>
<p>In Mack you can solve this problem by breaking your code out into Mack::ViewHelpers::&lt;module_name&gt; modules. IfÂ  you do this then that module is automatically included into all views. Modules in the Mack::ViewHelpers namespace do NOT get included into the controllers. If you want to include them into controllers you can use the include_safely_into method to achieve that goal.</p>
<h2>Conclusion</h2>
<p>Well, I hope you enjoyed, and are still awake, this brief overview of the way helpers work in Mack. They are different from Rails. I feel these differences are what make Mack helpers really really useful. Mack helpers do more then Rails, and these features can be not only be really powerful, but can really help to keep your code nice and DRY.</p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/03/18/helpers-in-mack/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>0.1.0: The Obligatory &#8216;Blog&#8217; Demo</title>
		<link>http://www.metabates.com/2008/03/04/the-obligatory-blog-demo/</link>
		<comments>http://www.metabates.com/2008/03/04/the-obligatory-blog-demo/#comments</comments>
		<pubDate>Tue, 04 Mar 2008 20:15:46 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[data mapper]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[mack]]></category>
		<category><![CDATA[post]]></category>
		<category><![CDATA[scaffold]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/2008/03/04/the-obligatory-blog-demo/</guid>
		<description><![CDATA[Ok, because every good framework should tell you how to create a blog, why should Mack be any different? Let&#8217;s start off with the basics. Is Mack installed? If not, here&#8217;s how: $ sudo gem install mack Great! Before we move on, make sure that the gem you installed is at LEAST version 0.1.0, otherwise, [...]]]></description>
			<content:encoded><![CDATA[<p>Ok, because every good framework should tell you how to create a blog, why should Mack be any different? Let&#8217;s start off with the basics. Is Mack installed? If not, here&#8217;s how:</p>
<pre>$ sudo gem install mack</pre>
<p>Great! Before we move on, make sure that the gem you installed is at LEAST version 0.1.0, otherwise, you&#8217;re not going to get very far in this tutorial. Now, let&#8217;s move on. Now let&#8217;s generate our kick ass new blog, and since we&#8217;re going to need some sort of database support for our blog, we&#8217;ll configure it to use DataMapper. If you don&#8217;t have DataMapper installed, please head over to <a href="http://datamapper.org" target="_blank">http://datamapper.org</a> to find out how to install it. Mack has support for ActiveRecord as well, but it&#8217;s just easier to get DataMapper going because you don&#8217;t have to deal with migrations.</p>
<pre>$ mack my_kick_ass_blog -o data_mapper
$ cd my_kick_ass_blog</pre>
<p>That should&#8217;ve created a whole bunch of files and folders for your blog. Now let&#8217;s generate some scaffold code for our blog:</p>
<pre>$ rake generate:scaffold name=posts</pre>
<p>That should&#8217;ve created even more files for you. One of those files is app/models/post.rb, let&#8217;s open that up, so we can edit it for DataMapper.</p>
<p>Edit the file so it looks something like this:</p>
<pre>class Post &lt; DataMapper::Base
  property :title, :string
  property :email, :string
  property :body, :text
  property :created_at, :datetime
  property :updated_at, :datetime

  validates_presence_of :title
  validates_presence_of :body
  validates_presence_of :email
end</pre>
<p>Now, I&#8217;m not going to go into detail as to what that&#8217;s doing, that&#8217;s for the guys at DataMapper to explain. Before we move on to the next step, you&#8217;ll probably want to crack open config/database.yml and edit it so it the paths to your database are correct, you&#8217;ll probably also want to go to your database system and make sure that the database name you configured in your config/database.yml is created, otherwise this will be a very short trip. I&#8217;ll wait while you do that. Finished, great! Let&#8217;s move on.</p>
<p>We need to now open a Mack console so we can create the tables needed for our blog.</p>
<pre>$ rake console
$ Post.table.create!
$ exit</pre>
<p>Ok, we should now have a posts table in our new database. Isn&#8217;t life wonderful? We&#8217;re so close to showing the world how wonderful we are as developers.</p>
<p>Now let&#8217;s edit our views, so they look something like this:</p>
<p>app/views/posts/index.html.erb:</p>
<pre>&lt;h1&gt;Listing posts&lt;/h1&gt;

&lt;table&gt;
  &lt;tr&gt;
    &lt;th&gt;Title&lt;/th&gt;
    &lt;th&gt;Body&lt;/th&gt;
    &lt;th&gt;Email&lt;/th&gt;
  &lt;/tr&gt;

&lt;% for post in @posts %&gt;
  &lt;tr&gt;
    &lt;td&gt;&lt;%=post.title %&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%=post.body %&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%=post.email %&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%= link_to("Show", posts_show_url(:id =&gt; post.id)) %&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%= link_to("Edit", posts_edit_url(:id =&gt; post.id)) %&gt;&lt;/td&gt;
    &lt;td&gt;&lt;%= link_to("Delete", posts_delete_url(:id =&gt; post.id), :method =&gt; :delete, :confirm =&gt; "Are you sure?") %&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;% end %&gt;
&lt;/table&gt;

&lt;br /&gt;

&lt;%= link_to("New Post", posts_new_url) %&gt;</pre>
<p>app/views/posts/edit.html.erb:</p>
<pre>&lt;h1&gt;Edit post&lt;/h1&gt;

&lt;%= error_messages_for :post %&gt;

&lt;form action="&lt;%= posts_update_url(:id =&gt; @post.id) %&gt;" class="edit_post" id="edit_post" method="post"&gt;
  &lt;input type="hidden" name="_method" value="put"&gt;
  &lt;p&gt;
    &lt;b&gt;Title&lt;/b&gt;&lt;br /&gt;
    &lt;input id="post_title" name="post[title]" size="30" type="text" value="&lt;%= @post.title %&gt;" /&gt;
  &lt;/p&gt;

  &lt;p&gt;
    &lt;b&gt;Body&lt;/b&gt;&lt;br /&gt;
    &lt;textarea id="post_body" name="post[body]"&gt;&lt;%= @post.body %&gt;&lt;/textarea&gt;
  &lt;/p&gt;

  &lt;p&gt;
    &lt;b&gt;Email&lt;/b&gt;&lt;br /&gt;
    &lt;input id="post_email" name="post[email]" size="30" type="text" value="&lt;%= @post.email %&gt;" /&gt;
  &lt;/p&gt;

  &lt;p&gt;
    &lt;input id="post_submit" name="commit" type="submit" value="Create" /&gt;
  &lt;/p&gt;
&lt;/form&gt;

&lt;%= link_to("Back", posts_index_url) %&gt;</pre>
<p>app/views/posts/show.html.erb:</p>
<pre>&lt;p&gt;
  &lt;b&gt;Title:&lt;/b&gt;
  &lt;%= @post.title %&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;b&gt;Body:&lt;/b&gt;
  &lt;%= @post.body %&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;b&gt;Email:&lt;/b&gt;
  &lt;%= @post.email %&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;b&gt;Created at:&lt;/b&gt;
  &lt;%= @post.created_at %&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;b&gt;Updated at:&lt;/b&gt;
  &lt;%= @post.updated_at %&gt;
&lt;/p&gt;

&lt;%= link_to("Edit", posts_edit_url(:id =&gt; @post.id)) %&gt; |
&lt;%= link_to("Back", posts_index_url) %&gt;</pre>
<p>app/views/posts/new.html.erb:</p>
<pre>&lt;h1&gt;New post&lt;/h1&gt;

&lt;%= error_messages_for :post %&gt;

&lt;form action="&lt;%= posts_create_url %&gt;" class="new_post" id="new_post" method="post"&gt;
  &lt;p&gt;
    &lt;b&gt;Title&lt;/b&gt;&lt;br /&gt;
    &lt;input id="post_title" name="post[title]" size="30" type="text" value="&lt;%= @post.title %&gt;" /&gt;
  &lt;/p&gt;

  &lt;p&gt;
    &lt;b&gt;Body&lt;/b&gt;&lt;br /&gt;
    &lt;textarea id="post_body" name="post[body]"&gt;&lt;%= @post.body %&gt;&lt;/textarea&gt;
  &lt;/p&gt;

  &lt;p&gt;
    &lt;b&gt;Email&lt;/b&gt;&lt;br /&gt;
    &lt;input id="post_email" name="post[email]" size="30" type="text" value="&lt;%= @post.email %&gt;" /&gt;
  &lt;/p&gt;

  &lt;p&gt;
    &lt;input id="post_submit" name="commit" type="submit" value="Create" /&gt;
  &lt;/p&gt;
&lt;/form&gt;

&lt;%= link_to("Back", posts_index_url) %&gt;</pre>
<p>Ok, so now we&#8217;ve created our forms, and setup our index page. Let&#8217;s actually go to the site and see it all works!</p>
<p>First we need to start the server:</p>
<p>$ rake server</p>
<p>Now let&#8217;s head on over to http://localhost:3000/posts and see what we&#8217;ve got. You should see a page that looks something like this:</p>
<p><img src="http://www.mackframework.com/wp-content/uploads/2008/03/12.png" alt="Blog Demo 1" /></p>
<p>Now let&#8217;s click on that &#8216;New Post&#8217; link and fill out the form:</p>
<p><img src="http://www.mackframework.com/wp-content/uploads/2008/03/21.png" alt="Blog Demo 2" /></p>
<p>Now, let&#8217;s hit that wonderful &#8216;Create&#8217; button and see what happens!</p>
<p><img src="http://www.mackframework.com/wp-content/uploads/2008/03/31.png" alt="Blog Demo 3" /></p>
<p>Congrats! You just created your first blog post! Now let&#8217;s head back to http://localhost:3000/posts and see what we&#8217;ve got.</p>
<p><img src="http://www.mackframework.com/wp-content/uploads/2008/03/41.png" alt="Blog Demo 4" /></p>
<p>Wonderful! Now all that&#8217;s left to do is to set our home page to our posts index page. Let&#8217;s open up our config/routes.rb and edit the following line:</p>
<pre>r.home_page "/", :controller =&gt; :default, :action =&gt; :index</pre>
<p>so that it&#8217;s now:</p>
<pre>r.home_page "/", :controller =&gt; :posts, :action =&gt; :index</pre>
<p>Now all you have to do is to restart your server and Bob&#8217;s your uncle when you hit http://localhost:3000 again you should your fantastic posts index page.</p>
<p>This concludes our brief introductory tutorial on getting going on Mack. Obviously Mack does a lot more, and I highly encourage you to read the <a href="http://api.mackframework.com">RDoc</a> to find out more about what it can do.</p>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/03/04/the-obligatory-blog-demo/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ORM Support</title>
		<link>http://www.metabates.com/2008/02/27/orm-support/</link>
		<comments>http://www.metabates.com/2008/02/27/orm-support/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 15:46:44 +0000</pubDate>
		<dc:creator>Mark Bates</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[active record]]></category>
		<category><![CDATA[data mapper]]></category>
		<category><![CDATA[orm]]></category>

		<guid isPermaLink="false">http://www.mackframework.com/2008/02/27/orm-support/</guid>
		<description><![CDATA[If you would like to add ORM support to your application, it&#8217;s simple. Out of the box Mack has support for two popular ORMs, ActiveRecord and DataMapper.Our tests show that DataMapper is 10x slower then ActiveRecord, but who knows, your mileage my vary. When you create your mack app you can do the following which [...]]]></description>
			<content:encoded><![CDATA[<p>If you would like to add ORM support to your application, it&#8217;s simple. Out of the box Mack has support for two popular ORMs, ActiveRecord and DataMapper.Our tests show that DataMapper is 10x slower then ActiveRecord, but who knows, your mileage my vary.</p>
<p>When you create your mack app you can do the following which will add ORM support to your generated app:</p>
<pre>$ mack my_cool_mack_app -o activerecord</pre>
<p>If you already have a mack app you can very easily add ORM support by adding the following configuration parameter to the default.yml file:</p>
<pre>mack::orm: activerecord</pre>
<p>And also add a database.yml file to your config directory that looks like this:</p>
<pre>development:
  adapter: mysql
  database: my_cool_mack_app_development
  host: localhost
  username: root
  password:

test:
  adapter: mysql
  database: my_cool_mack_app_test
  host: localhost
  username: root
  password:

production:
  adapter: mysql
  database: my_cool_mack_app_production
  host: localhost
  username: root
  password:</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.metabates.com/2008/02/27/orm-support/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.815 seconds -->

