<?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>Tea-Driven Development &#187; rails</title>
	<atom:link href="http://blog.mattwynne.net/tag/rails/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mattwynne.net</link>
	<description>Matt Wynne taking it one tea at a time</description>
	<lastBuildDate>Tue, 10 Jan 2012 20:07:10 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Two Truths I&#8217;ve Learned About Writing Clean Rails Apps</title>
		<link>http://blog.mattwynne.net/2011/03/04/two-truths-ive-learned-about-writing-clean-rails-apps/</link>
		<comments>http://blog.mattwynne.net/2011/03/04/two-truths-ive-learned-about-writing-clean-rails-apps/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 13:28:01 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Ruby Programming]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2011/03/04/two-truths-ive-learned-about-writing-clean-rails-apps/</guid>
		<description><![CDATA[In summary: Implement every feature without javascript first, add javascript as a progressive enhancement Stick to REST. Always. Now I&#8217;m as suspicious of absolute rules as you probably are, but these two have served me extremely well in keeping my Rails code clean and easy to maintain. I&#8217;m happy to push the boat out and [...]]]></description>
			<content:encoded><![CDATA[<p>In summary:</p>

<ul>
<li>Implement every feature without javascript first, add javascript as a progressive enhancement</li>
<li>Stick to REST. Always.</li>
</ul>

<p>Now I&#8217;m as <a href="http://fragmental.tw/2011/01/04/rules_of_thumb_are_warning_bells.html">suspicious of absolute rules</a> as you probably are, but these two have served me extremely well in keeping my Rails code clean and easy to maintain. I&#8217;m happy to push the boat out and call them truths, my truths anyway.</p>

<p>Let me explain.</p>

<h1>Progressive Enhancement</h1>

<p>When I first started at Songkick, Cucumber was just emerging and webrat was the new kid on the testing block. Although using Selenium for full-stack javascript testing was possible with webrat, it wasn&#8217;t easy and we quickly made a decision: we would build the first iteration of every feature to work without javascript. This was mainly driven by pragmatism: we could easily use webrat to test the app through Rails integration testing stack, and these tests ran quickly rather than waiting for a browser to start up.</p>

<p>What happened surprised us. We would receive fancy designs from our designers which could only be implemented with fairly complex javascript. Because of our rule, we had to figure out how to deliver the same behaviour using basic HTTP posts and gets of forms and URLs. This required us to simplify the designs for our first iteration. We got a little push-back at first but we were a tight team and the designers quickly caught on. Especially when we started shipping these iteration one features quickly and reliably. And funnily enough, it turned out that often these simple HTTP-only versions of the features were actually fine, and the designers decided we should move onto other stuff, instead of building all that complex javascript that had been implied by their earlier designs.</p>

<p>So this rule had helped us to do the simple thing. We shipped features and moved on.</p>

<p>When we did have to add javascript, we added it on top of the existing working HTTP-only implementation, and we got another surprise: it was easy! Nearly every time, because we&#8217;d built the server-side infrastructure to a clean, standard pattern, the javascript we needed was clean and simple to write.</p>

<p>Which leads me to my next truth&#8230;</p>

<h1>Stick to REST. Always.</h1>

<p>I&#8217;ve always felt a little uncomfortable with Rails&#8217; controllers. They violate the Single Responsibility Principle for me. I&#8217;d prefer a pattern where I had a separate Request class for each action, rather than a few largely unrelated methods on the same controller class. But Rails is there and there&#8217;s a lot else to like, so let&#8217;s not get into that.</p>

<p>We all know it&#8217;s a bad idea to <a href="http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model">let our controllers bloat</a> and something I&#8217;ve been enjoying greatly lately is <a href="http://blog.plataformatec.com.br/author/josevalim/">Jose Valim</a>&#8216;s <a href="https://github.com/josevalim/inherited_resources">Inherited Resources</a>. By sticking to this pattern, you push all the logic into your domain model, and keep the controllers focussed on what they need to do: handling web requests.</p>

<p>You end up with more controllers, and more models too. You create model objects that &#8212; Gosh! &#8212; don&#8217;t represent database tables, but represent other domain concepts instead. Altogether though, you end up with smaller, more focussed classes that are easier to test and easier to read and understand.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2011/03/04/two-truths-ive-learned-about-writing-clean-rails-apps/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Rails Tip: Use Polymorphism to Extend your Controllers at Runtime</title>
		<link>http://blog.mattwynne.net/2009/07/11/rails-tip-use-polymorphism-to-extend-your-controllers-at-runtime/</link>
		<comments>http://blog.mattwynne.net/2009/07/11/rails-tip-use-polymorphism-to-extend-your-controllers-at-runtime/#comments</comments>
		<pubDate>Sat, 11 Jul 2009 20:35:04 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Ruby Programming]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[Polymorphism]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2009/07/11/rails-tip-use-polymorphism-to-extend-your-controllers-at-runtime/</guid>
		<description><![CDATA[Metaprogramming in Ruby comes in for quite a bit of stick at times, the accusation being that code which modifies itself at runtime can be hard to understand. As Martin Fowler recently described, there&#8217;s a sweet spot where you use just enough to get some of the incredible benefits that Ruby offers, without leaving behind [...]]]></description>
			<content:encoded><![CDATA[<p>Metaprogramming in Ruby comes in for quite a bit of stick at times, the accusation being that code which modifies itself at runtime can be hard to understand. As <a href="http://martinfowler.com/articles/rubyAtThoughtWorks.html#IsARubyCode-baseHardToUnderstand">Martin Fowler recently described</a>, there&#8217;s a sweet spot where you use just enough to get some of the incredible benefits that Ruby offers, without leaving behind a minefield for future developers who&#8217;ll have to maintain your code.</p>

<p>One of my favourite techniques uses the <a href="http://ruby-doc.org/core/classes/Object.html#M000335">Object#extend</a> method, which allows you to mix in the methods from a module to a specific instance of a class at run-time. In my quest to <a href="http://www.antiifcampaign.com/">eliminate as much conditional logic as possible</a> from my code, I&#8217;ve seen a common pattern emerge a few times. Here&#8217;s an example from a refactoring session I paired on with my colleague <a href="http://craig-mackenzie.com/">craig</a>.</p>

<p>We start with a Rails controller which handles user authentication. Over the passing iterations, it has grown to support not only bog-standard logins from users of the main web application, but a form that&#8217;s displayed on a 3rd-party partner site, as well as during the installation of a rich-client GUI app. All these clients need slightly different behaviour &#8211; different templates or layout to be rendered, and different destination pages to redirect to when the login has succeded.</p>

<p>Sadly the hackers passing through this controller have not been great <a href="http://www.informit.com/articles/article.aspx?p=1235624&amp;seqNum=6">boy scouts</a>, and the code has started to get pretty unpleasant. This code is simplified for clarity:</p>

<p><div>
<pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SessionsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> new
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:installer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      render <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      render <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'modal'</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</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> = <span style="color:#996600;">&quot;Please enter a username&quot;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render_new_action
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">unless</span> user = User.<span style="color:#9900CC;">authenticate</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:password</span><span style="color:#006600; font-weight:bold;">&#93;</span><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> = <span style="color:#996600;">&quot;Sorry, that username was not recognised&quot;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render_new_action
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    set_logged_in_user<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:installer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@username</span> = user.<span style="color:#9900CC;">username</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_done'</span>, <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">elsif</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:third_party</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;third_party/#{params[:third_party]}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> redirect_to<span style="color:#006600; font-weight:bold;">&#40;</span>success_url<span style="color:#006600; font-weight:bold;">&#41;</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></p>

<p>Notice how the conditional logic has a similar structure in both actions. Our refactoring starts by introducing a before_filter which works out the necessary extension:</p>

<p><div>
<pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SessionsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
&nbsp;
  before_filter <span style="color:#ff3333; font-weight:bold;">:extend_for_client</span>
&nbsp;
  ....
&nbsp;
  <span style="color:#9900CC;">private</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> extend_for_client
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">extend</span><span style="color:#006600; font-weight:bold;">&#40;</span>client_exension_module<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> client_exension_module
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> client_extension_module
    <span style="color:#0000FF; font-weight:bold;">return</span> InstallerClient <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:installer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> ThirdPartyClient <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:third_party</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">module</span> InstallerClient
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">module</span> ThirdPartyClient
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre>
</div></p>

<p>Notice that we don&#8217;t bother extending the controller for the &#8216;else&#8217; case of the conditional statements &#8211; we&#8217;ll leave that behaviour in the base controller, only overriding it where necessary.</p>

<p>Now let&#8217;s extract the client-specific code out of the create action into a method that we&#8217;ll override in the modules:</p>

<p><div>
<pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SessionsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
&nbsp;
  ...
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</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> = <span style="color:#996600;">&quot;Please enter a username&quot;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render_new_action 
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">unless</span> user = User.<span style="color:#9900CC;">authenticate</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:password</span><span style="color:#006600; font-weight:bold;">&#93;</span><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> = <span style="color:#996600;">&quot;Sorry, that username was not recognised&quot;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render_new_action 
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    set_logged_in_user<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    handle_successful_login
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private 
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> handle_successful_login
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:installer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0066ff; font-weight:bold;">@username</span> = user.<span style="color:#9900CC;">username</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_done'</span>, <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">elsif</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:third_party</span><span style="color:#006600; font-weight:bold;">&#93;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;third_party/#{params[:third_party]}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">else</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> redirect_to<span style="color:#006600; font-weight:bold;">&#40;</span>success_url<span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  ...</pre>
</div></p>

<p>Finally, we can the client-specific code into the appropriate module, leaving the default behaviour in the controller:</p>

<p><div>
<pre class="ruby" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> SessionsController <span style="color:#006600; font-weight:bold;">&lt;</span> ApplicationController
&nbsp;
  before_filter <span style="color:#ff3333; font-weight:bold;">:extend_for_client</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> new
    render <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'modal'</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> create
    <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>.<span style="color:#9900CC;">blank</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> = <span style="color:#996600;">&quot;Please enter a username&quot;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render_new_action 
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">unless</span> user = User.<span style="color:#9900CC;">authenticate</span><span style="color:#006600; font-weight:bold;">&#40;</span>params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:username</span><span style="color:#006600; font-weight:bold;">&#93;</span>, params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:password</span><span style="color:#006600; font-weight:bold;">&#93;</span><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> = <span style="color:#996600;">&quot;Sorry, that username was not recognised&quot;</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render_new_action 
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    set_logged_in_user<span style="color:#006600; font-weight:bold;">&#40;</span>user<span style="color:#006600; font-weight:bold;">&#41;</span>
&nbsp;
    handle_successful_login
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private 
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> handle_successful_login
    <span style="color:#0000FF; font-weight:bold;">return</span> redirect_to<span style="color:#006600; font-weight:bold;">&#40;</span>success_url<span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> extend_for_client
    <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">extend</span><span style="color:#006600; font-weight:bold;">&#40;</span>client_exension_module<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">if</span> client_exension_module
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> client_extension_module
    <span style="color:#0000FF; font-weight:bold;">return</span> InstallerClient <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:installer</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#0000FF; font-weight:bold;">return</span> ThirdPartyClient <span style="color:#9966CC; font-weight:bold;">if</span> params<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:third_party</span><span style="color:#006600; font-weight:bold;">&#93;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">module</span> InstallerClient
    <span style="color:#9966CC; font-weight:bold;">def</span> new
      render <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span>, <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
    private 
&nbsp;
    <span style="color:#9966CC; font-weight:bold;">def</span> handle_successful_login
      <span style="color:#0066ff; font-weight:bold;">@username</span> = user.<span style="color:#9900CC;">username</span>
      <span style="color:#0000FF; font-weight:bold;">return</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_done'</span>, <span style="color:#ff3333; font-weight:bold;">:layout</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">'installer_signup'</span> <span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">module</span> ThirdPartyClient
    <span style="color:#9966CC; font-weight:bold;">def</span> handle_successful_login
      <span style="color:#0000FF; font-weight:bold;">return</span> render<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:template</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;third_party/#{params[:third_party]}&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</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></p>

<p>Polymorphism is one of the power-features of an object-oriented language, and Ruby&#8217;s ability to flex this muscle at run-time opens up some really elegant options.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2009/07/11/rails-tip-use-polymorphism-to-extend-your-controllers-at-runtime/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MagLev: Death of the Relational Database?</title>
		<link>http://blog.mattwynne.net/2009/01/07/maglev-death-of-the-relational-database/</link>
		<comments>http://blog.mattwynne.net/2009/01/07/maglev-death-of-the-relational-database/#comments</comments>
		<pubDate>Wed, 07 Jan 2009 14:26:49 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Agile / Lean Software Development]]></category>
		<category><![CDATA[Ruby Programming]]></category>
		<category><![CDATA[Future]]></category>
		<category><![CDATA[MagLev]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2009/01/07/maglev-death-of-the-relational-database/</guid>
		<description><![CDATA[I just got around to watching Avi Bryant&#8217;s talk on MagLev, a new Ruby VM built on top of GemStone&#8217;s Smalltalk VM. http://www.vimeo.com/1147409 Presumably this is the kind of thing Smalltalkers have been able to do for decades, but to me the prospect of having this kind of freedom on a Ruby platform is very [...]]]></description>
			<content:encoded><![CDATA[<p>I just got around to watching Avi Bryant&#8217;s talk on <a href="http://ruby.gemstone.com/">MagLev</a>, a new Ruby VM built on top of GemStone&#8217;s Smalltalk VM.</p>

<p><a href="http://www.vimeo.com/1147409">http://www.vimeo.com/1147409</a></p>

<p>Presumably this is the kind of thing Smalltalkers have been able to do for decades, but to me the prospect of having this kind of freedom on a Ruby platform is very exciting. Terrific stuff. I wonder what performance is like.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2009/01/07/maglev-death-of-the-relational-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Behaviour-Driving Routes in Rails with RSpec</title>
		<link>http://blog.mattwynne.net/2008/08/08/behaviour-driving-routes-in-rails-with-rspec/</link>
		<comments>http://blog.mattwynne.net/2008/08/08/behaviour-driving-routes-in-rails-with-rspec/#comments</comments>
		<pubDate>Fri, 08 Aug 2008 16:46:10 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Agile / Lean Software Development]]></category>
		<category><![CDATA[BDD]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[rspec]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[TDD]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2008/08/08/behaviour-driving-routes-in-rails-with-rspec/</guid>
		<description><![CDATA[One thing that isn&#8217;t documented very well for RSpec is how to test your routes. I came across an old post on the rspec mailing list which described a great way to do this: describe TasksController &#34;routing&#34; do &#160; it &#34;should route POST request for /tasks to the 'create' action&#34; do params_from(:post, &#34;/tasks&#34;).should == {:controller [...]]]></description>
			<content:encoded><![CDATA[<p>One thing that isn&#8217;t documented very well for RSpec is how to test your routes.</p>

<p>I came across an old post on the rspec mailing list which described a great way to do this:</p>

<p><div>
<pre class="txt" style="font-family:monospace;">describe TasksController &quot;routing&quot; do
&nbsp;
    it &quot;should route POST request for /tasks to the 'create' action&quot; do
        params_from(:post, &quot;/tasks&quot;).should == {:controller =&gt;; &quot;tasks&quot;, :action =&gt;; &quot;create&quot;}
    end
&nbsp;
end</pre>
</div></p>

<p>Very nice.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2008/08/08/behaviour-driving-routes-in-rails-with-rspec/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DataMapper: A Better ORM for Ruby</title>
		<link>http://blog.mattwynne.net/2008/05/23/datamapper-a-better-orm-for-ruby/</link>
		<comments>http://blog.mattwynne.net/2008/05/23/datamapper-a-better-orm-for-ruby/#comments</comments>
		<pubDate>Fri, 23 May 2008 07:11:36 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[Agile / Lean Software Development]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[orm]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2008/05/23/datamapper-a-better-orm-for-ruby/</guid>
		<description><![CDATA[One of the things that&#8217;s always irritated my about rails&#8217; ActiveRecord framework is the way that the domain model lives in the database.Don&#8217;t get me wrong: it&#8217;s very clever, and a great showcase for ruby&#8217;s metaprogramming features, which will blow average C# / Java mind the mind when they first see it. In rails, you [...]]]></description>
			<content:encoded><![CDATA[<p>One of the things that&#8217;s always irritated my about rails&#8217; ActiveRecord framework is the way that the domain model lives in the database.Don&#8217;t get me wrong: it&#8217;s very clever, and a great showcase for ruby&#8217;s metaprogramming features, which will blow average C# / Java mind the mind when they first see it.</p>

<p>In rails, you build a database of your domain model, and create empty classes with the names of the domain entities (conventionally the singular of a database table name) which inherit from ActiveRecord. ActiveRecord then looks at your database, and using the magic of metaprogramming, hydrates your object with a bunch of properties that map to the database fields.</p>

<p>But I prefer to write my models in the code, and if you do too, you might want to take a look at <a href="http://datamapper.org/">DataMapper</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2008/05/23/datamapper-a-better-orm-for-ruby/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Painless RMagick Install for Ruby on Rails</title>
		<link>http://blog.mattwynne.net/2007/07/01/painless-rmagick-install/</link>
		<comments>http://blog.mattwynne.net/2007/07/01/painless-rmagick-install/#comments</comments>
		<pubDate>Sun, 01 Jul 2007 01:26:26 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[file_column]]></category>
		<category><![CDATA[imagemagick]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[rmagick]]></category>
		<category><![CDATA[thumbnails]]></category>
		<category><![CDATA[ui]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2007/07/01/painless-rmagick-install/</guid>
		<description><![CDATA[One of the ironies and frustrations I find of working with open-source software is that things are changing so fast (yay!) that the documentation you find is nearly always out of date (boo!). Trying to figure out how to get the rmagick component of the handy file_column rails plug-in to play nice, I came across [...]]]></description>
			<content:encoded><![CDATA[<p>One of the ironies and frustrations I find of working with open-source software is that things are changing so fast (yay!) that the documentation you find is nearly always out of date (boo!).</p>

<p>Trying to figure out how to get the <a href="http://rmagick.rubyforge.org/">rmagick</a> component of the handy <a href="http://www.kanthak.net/opensource/file_column/">file_column</a> rails plug-in to play nice, I came across numerous gruesome posts involving 3 hour sessions building rmagick from source, sacrificing goats, etc. Yikes.</p>

<p>Then I came across <a href="http://www.danielfischer.com/2007/06/20/an-even-easier-way-to-install-rmagick-for-ruby-on-rails-development/">this great piece of news</a> and suddenly things clicked into place. Ahhh.</p>

<p>Ten minutes later, a sprinkle of <a href="http://blog.caboo.se/articles/2006/01/09/file_column-magick-and-versions">this</a>, and I have thumbnail images all over my site. Too easy!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2007/07/01/painless-rmagick-install/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Nested Controllers and Broken link_to</title>
		<link>http://blog.mattwynne.net/2007/06/16/nested-controllers-and-broken-link_to/</link>
		<comments>http://blog.mattwynne.net/2007/06/16/nested-controllers-and-broken-link_to/#comments</comments>
		<pubDate>Sat, 16 Jun 2007 19:40:17 +0000</pubDate>
		<dc:creator>Matt</dc:creator>
				<category><![CDATA[books]]></category>
		<category><![CDATA[controllers]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://blog.mattwynne.net/2007/06/16/nested-controllers-and-broken-link_to/</guid>
		<description><![CDATA[So my first little rails app is taking it&#8217;s baby steps in the wild today, and some users should hit the site over the weekend&#8230; Exciting stuff. I&#8217;ve written an admin area for the site, and with only a tentative grasp on the whys and wherefores, I&#8217;ve copied something I saw in the mephisto source [...]]]></description>
			<content:encoded><![CDATA[<p>So my first little rails app is taking it&#8217;s baby steps in the wild today, and some users should hit the site over the weekend&#8230; Exciting stuff.</p>

<p>I&#8217;ve written an admin area for the site, and with only a tentative grasp on the whys and wherefores, I&#8217;ve copied something I saw in the mephisto source code and used &#8216;nested controllers&#8217; to keep the admin code tucked away from the rest:
<pre>
<code>
$script/generate controller admin/users
$script/generate controller admin/stuff
</code></pre>
For want of a better way, I put a base class for the admin controllers into the application.rb file (can&#8217;t remember where I picked this tip up) and put a one-line before_filter on that class to check whether the user has the appropriate rights. Sweet.</p>

<p>The little gotcha with this was that a lot of my existing link<em>to and redirect</em>to calls didn&#8217;t work from within the admin area, because I guess the :controller value in the options is relative. Adding a forward-slash to the controller name fixes it up:
<pre>
<code>
&lt;%= link_to 'home', :controller =&gt; '/home' %&gt;
</code></pre>
Looks like <a href="http://blogs.herod.net/steven/nesting-controllers-with-rubyonrails/">not the only one</a> to have hit this little bump.</p>

<p>I think I need a new rails book: I&#8217;m starting to leave my trusty <a href="http://www.pragmaticprogrammer.com/titles/rails/">pragprog</a> book behind. Any recommendations out there people?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mattwynne.net/2007/06/16/nested-controllers-and-broken-link_to/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

