<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Medium eXposure</title>
	
	<link>http://mediumexposure.com</link>
	<description>by Maxim Chernyak</description>
	<lastBuildDate>Sun, 07 Feb 2010 09:11:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/mediumexposure" /><feedburner:info uri="mediumexposure" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>script/migrator for navigating migrations</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/CV1wxtiOx1Y/</link>
		<comments>http://mediumexposure.com/scriptmigrator-for-navigating-migrations/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 03:02:39 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false">http://mediumexposure.com/scriptmigrator-for-navigating-migrations/</guid>
		<description><![CDATA[I got tired of digging through migrations, so here&#8217;s a simple console navigator. The instructions are all in there.


]]></description>
			<content:encoded><![CDATA[<p>I got tired of digging through migrations, so here&#8217;s a simple console navigator. The instructions are all in there.</p>

<script src="http://gist.github.com/297337.js?file=migrator"></script>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/CV1wxtiOx1Y" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/scriptmigrator-for-navigating-migrations/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/scriptmigrator-for-navigating-migrations/</feedburner:origLink></item>
		<item>
		<title>Rails 3 Reading Material</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/RLsbeNY5qls/</link>
		<comments>http://mediumexposure.com/rails-3-reading-material/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 10:25:45 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://mediumexposure.com/?p=69</guid>
		<description><![CDATA[Rails 3 is going to bring a lot of new stuff to the table. Wouldn&#8217;t hurt to organize some reading material in categorized and chronological order. So here goes whatever I scavenged so far. Leave comments so I can add more links or if I should mark something as obsolete.

Router


Revamped Routes in Rails 3  [...]]]></description>
			<content:encoded><![CDATA[<p>Rails 3 is going to bring a lot of new stuff to the table. Wouldn&#8217;t hurt to organize some reading material in categorized and chronological order. So here goes whatever I scavenged so far. Leave comments so I can add more links or if I should mark something as <em>obsolete</em>.</p>

<h2>Router</h2>

<ul>
<li><a href="http://rizwanreza.com/2009/12/20/revamped-routes-in-rails-3">Revamped Routes in Rails 3 </a> (12/20/09) — Examples of usage of the Rails 3 router.</li>
<li><a href="http://yehudakatz.com/2009/12/20/generic-actions-in-rails-3/">Generic Actions in Rails 3</a> (12/20/09) — Interesting things you can do with Rails 3 routes.</li>
<li><a href="http://yehudakatz.com/2009/12/26/the-rails-3-router-rack-it-up/">The Rails 3 Router: Rack it Up</a> (12/26/09) — A description of important design decisions made for the new Rails 3 router.</li>
</ul>

<h2>ActiveRecord</h2>

<ul>
<li><a href="http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord">ActiveModel: Make Any Ruby Object Feel Like ActiveRecord</a> (01/10/10) — Learn about the ActiveModel API.</li>
<li><a href="http://hasmanyquestions.wordpress.com/2010/01/17/let-your-sql-growl-in-rails-3/">Let your SQL Growl in Rails 3</a> (01/17/10) — A neat trick and an example on how to use Rails 3 subscription models.</li>
<li><a href="http://m.onkey.org/2010/1/22/active-record-query-interface">Active Record Query Interface 3.0</a> (01/22/10) &#8211; The new ActiveRecord API (based on ARel) thoroughly explained.</li>
</ul>

<h2>Controllers</h2>

<ul>
<li><a href="http://august.lilleaas.net/blog/dynamic-session-expiration-time-in-rails-3">Dynamic session expiration time in Rails 3</a> (01/16/10) — An insight on how Rails 3 handles session cookies and a convenience plugin.</li>
<li><a href="http://www.engineyard.com/blog/2010/render-options-in-rails-3/">Render Options in Rails 3</a> (01/18/10) — Those <code>render</code> methods you call in your controllers: learn about their options in Rails 3.</li>
</ul>

<h2>ActionMailer</h2>

<ul>
<li><a href="http://lindsaar.net/2010/1/26/new-actionmailer-api-in-rails-3">New ActionMailer API in Rails 3.0</a> (01/26/10) — ActionMailer now shares lots of logic with controllers, learn its new API.</li>
</ul>

<h2>Views</h2>

<ul>
<li><a href="http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0">SafeBuffers and Rails 3.0</a> (02/01/10) — Learn about html&#95;safe strings in Rails 3.0.</li>
</ul>

<h2>Generators</h2>

<ul>
<li><a href="http://caffeinedd.com/guides/331-making-generators-for-rails-3-with-thor">Making Generators for Rails 3 with Thor</a> (01/15/10) — A thorough tutorial on how to create, gemify, and test Rails 3 generators.</li>
<li><a href="http://blog.plataformatec.com.br/2010/01/discovering-rails-3-generators">Discovering Rails 3 generators</a> (01/18/10) — A few important points to know about Rails 3 generators.</li>
</ul>

<h2>Running Rails 3 App</h2>

<ul>
<li><a href="http://yehudakatz.com/2009/12/31/spinning-up-a-new-rails-app/">Spinning up a new Rails app</a> (12/31/09) — One of the first posts on how to spin up a new Rails 3 app.</li>
<li><a href="http://cakebaker.42dh.com/2010/01/17/rails-3-and-passenger/">Rails 3 and Passenger</a> (01/17/10) — A few tips on how to run Rails 3 on passenger.</li>
<li><a href="http://cardarella.blogspot.com/2010/01/rails-2-rails-3-side-by-side.html">Rails 2 &amp; Rails 3 side by side</a> (01/28/10) — Juggling both versions of rails on the same system (check comments too).</li>
<li><a href="http://matt-hulse.com/articles/2010/01/30/from-zero-to-rails3-on-windows-in-600-seconds/">From Zero to Rails3 on Windows in 600 seconds</a> (01/30/10) — Get a Rails 3 app running on Windows.</li>
</ul>

<h2>Upgrading to Rails 3</h2>

<ul>
<li><a href="http://caffeinedd.com/guides/348-upgrading-to-rails-3">Upgrading an Application to Rails 3 — Part 1</a> (01/17/10) — Learn how to upgrade your Rails 2 app to Rails 3.</li>
<li><a href="http://www.madcowley.com/madcode/?p=12">Migrating a Rails App from 2.x to 3.0</a> (01/17/10) — Another tutorial on steps needed to upgrade your Rails app.</li>
<li><a href="http://rails3.community-tracker.com/permalinks/5/notes-from-the-field-upgrading-to-rails-3">Notes from the field upgrading to Rails 3</a> (01/20/10) — Thanks to <a href="http://bugmash.com/">bugmash</a> there are now a few of these upgrade guides.</li>
<li><a href="http://darwinweb.net/articles/82">Getting Up To Speed With Rails 3</a> (01/22/10) — Good article on upgrading to Rails 3 and deploying with capistrano and passenger.</li>
<li><a href="http://omgbloglol.com/post/353978923/the-path-to-rails-3-approaching-the-upgrade">The Path to Rails 3: Approaching the upgrade</a> (01/26/10) — Second part in series on understanding Rails 3, this one focusing on upgrade of existing app.</li>
<li><a href="http://omgbloglol.com/post/359147788/rails-upgrade-automating-a-portion-of-the-rails-3">rails-upgrade: Automating a portion of the Rails 3 upgrade process</a> (01/29/10) — Third part where a plugin is introduced to help automate the upgrade.</li>
<li><a href="http://omgbloglol.com/post/364624593">rails-upgrade is now an official plugin</a> (02/01/10) — rails-upgrade is now an official rails tool (as in it sits under <a href="http://github.com/rails">github.com/rails</a> and rails team takes part in maintaining it).</li>
</ul>

<h2>Plugin/Gem Compatibility</h2>

<ul>
<li><a href="http://blog.trydionel.com/2010/01/16/rails-bugmash-2010/">Rails Bugmash 2010</a> (01/16/10) — Notes on how to get certain popular gems/plugins to run on Rails 3.</li>
<li><a href="http://blazingcloud.net/2010/01/17/notes-from-rails-3-bugmash/">Notes from Rails 3 bugmash</a> (01/17/10) — Another set of plugin/gem compatibility notes and Rails 3 discoveries.</li>
<li><a href="http://wiki.rubyonrails.org/rails/version3/plugins_and_gems">Rails 3 Plugins and Gems</a> — this wiki page lists  major plugins and gems which have been verified to be Rails 3 compatible (or not).</li>
</ul>

<h2>Overall Architecture</h2>

<ul>
<li><a href="http://www.engineyard.com/blog/2009/my-five-favorite-things-about-rails-3/">My Five Favorite Things About Rails 3</a> (08/18/09) — Early view on what&#8217;s getting into Rails 3</li>
<li><a href="http://omgbloglol.com/post/344792822/the-path-to-rails-3-introduction">The Path to Rails 3: Introduction</a> (01/20/10) — A detailed description of architectural changes in Rails 3 (with pics).</li>
</ul>

<h2>Yehuda Katz Series on Rails 3 Progress</h2>

<ul>
<li><a href="http://www.engineyard.com/blog/2009/rails-and-merb-merge-the-anniversary-part-1-of-6/">Rails and Merb Merge: The Anniversary (Part 1 of 6)</a> (12/23/09) — On refactoring Rails components for modularity.</li>
<li><a href="http://www.engineyard.com/blog/2009/rails-and-merb-merge-performance-part-2-of-6/">Rails and Merb Merge: Performance (Part 2 of 6)</a> (12/29/09) — On improving rendering/routing performance.</li>
<li><a href="http://www.engineyard.com/blog/2010/rails-and-merb-merge-plugin-api-part-3-of-6/">Rails and Merb Merge: Plugin API (Part 3 of 6)</a> (01/11/10) — On API for plugin developers.</li>
<li><a href="http://www.engineyard.com/blog/2010/rails-and-merb-merge-rails-core-part-4-of-6/">Rails and Merb Merge: Rails Core (Part 4 of 6)</a> (01/22/10) — On refactoring Rails core for modularity.</li>
</ul>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/RLsbeNY5qls" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/rails-3-reading-material/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/rails-3-reading-material/</feedburner:origLink></item>
		<item>
		<title>Multiple Table Inheritance with ActiveRecord</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/U3uFAuj6u8E/</link>
		<comments>http://mediumexposure.com/multiple-table-inheritance-active-record/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 04:01:40 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[snippets]]></category>
		<category><![CDATA[solutions]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://mediumexposure.com/?p=68</guid>
		<description><![CDATA[Update 02/02/10: There are two new sections: Fixing method_missing and Handling attributes hash, which fix a few issues that popped up since first post.

If you aren&#8217;t interested in reading all the details you may want to make the long story short.

Imagine writing an online shop with different types of products. Normally all products would have [...]]]></description>
			<content:encoded><![CDATA[<p class="note"><strong>Update 02/02/10: </strong>There are two new sections: Fixing method_missing and Handling attributes hash, which fix a few issues that popped up since first post.</p>

<p class="note">If you aren&#8217;t interested in reading all the details you may want to <a href="#mti-the-short-story">make the long story short</a>.</p>

<p>Imagine writing an online shop with different types of products. Normally all products would have common attributes such as <code>title</code> and <code>price</code>. Some attributes will likely differ. <code>Tee</code> may have <code>size</code> such as S, M, or L, while a <code>Pen</code> could have an <code>ink_color</code>. It&#8217;s easy to see that <code>Tee</code> is a <code>Product</code>, and so is <code>Pen</code>. We are looking at an <em>is&#95;a</em> relationship. When I program this type of relationship I usually use inheritance.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Product <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Tee <span style="color:#006600; font-weight:bold;">&lt;</span> Product<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Pen <span style="color:#006600; font-weight:bold;">&lt;</span> Product<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>This inheritance looks reasonable, but now we have to come up with relational database structure. We need to find a way to store tee&#8217;s own attributes, pen&#8217;s own attributes, as well as their common (product&#8217;s) attributes without duplication. Some databases (PostgreSQL) provide support for table inheritance, but it&#8217;s a specialized feature which ties you down to the given db.</p>

<h2>Single Table Inheritance</h2>

<p>ActiveRecord provides only one way to handle a <em>is&#95;a</em> relationship which is <a href="http://en.wikipedia.org/wiki/Single_Table_Inheritance">Single Table Inheritance</a>. You&#8217;d have to create a table looking somewhat like the following.</p>

<p><pre></pre></p>

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; +----+------+-------+-----------------+------+-----------+<br />
&nbsp; | id | type | price | title &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; | size | ink_color |<br />
&nbsp; +----+------+-------+-----------------+------+-----------+<br />
&nbsp; | 1 &nbsp;| Tee &nbsp;| 1000 &nbsp;| tie-dye t-shirt | M &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |<br />
&nbsp; | 2 &nbsp;| Pen &nbsp;| 500 &nbsp; | ball pen &nbsp; &nbsp; &nbsp; &nbsp;| &nbsp; &nbsp; &nbsp;| blue &nbsp; &nbsp; &nbsp;|<br />
&nbsp; +----+------+-------+-----------------+------+-----------+</div></div>

<p></p>

<p>The problem here is that all attributes are stored in the same table. It&#8217;s likely that soon the number of attributes will grow unmanageable, and most of them will always stay <code>NULL</code> since they&#8217;ll be specific to only one <code>type</code>.</p>

<h2>Polymorphic has_one Association</h2>

<p>A <code>has_one</code> association allows us to split out tees, pens, and products into three different tables. In fact — as you&#8217;re about to see — this is the only way to get what we want. The problem is that it creates a <code>has_a</code> relationship, and we want <code>is_a</code>. Since there isn&#8217;t much choice, we can make it <em>look</em> like we have an is_a relationship, which I&#8217;m about to show.</p>

<h2>Multiple Table Inheritance (Simulated)</h2>

<p>I was speaking with <a href="http://twitter.com/fowlduck">the awesome @fowlduck</a> over at #railsbridge IRC channel about ways to achieve something like MTI with Active Record. He pointed me to a pastie where he implemented an MTI-like behavior and called it a &#8220;hydra&#8221; pattern, which I subsequently cleaned up a bit.</p>

<p>So we want to have 3 tables in the database.</p>

<ul>
<li>product_properties</li>
<li>tees</li>
<li>pens</li>
</ul>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> ProductProperties <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:polymorphic</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> :<span style="color:#5A0A0A; font-weight:bold;">destroy</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Tee <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Pen <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>Immediately we can see duplicated code between Tee and Pen. This can be easily solved with a mixin.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">included</span><span style="color:#006600; font-weight:bold;">&#40;</span>base<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Tee <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> Sellable<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Pen <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> Sellable<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>Now comes another issue. Every time we want to access price or title attributes (stored in product_properties) we have to call <code>@tee.product_properties.price</code>. This isn&#8217;t very convenient, especially considering that product_properties has to be built first in case it doesn&#8217;t exist. So let&#8217;s ensure it&#8217;s always built by updating the module.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">included</span><span style="color:#006600; font-weight:bold;">&#40;</span>base<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#9900CC;">alias_method_chain</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:autobuild</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> product_properties_with_autobuild<br />
&nbsp; &nbsp; &nbsp; product_properties_without_autobuild <span style="color:#006600; font-weight:bold;">||</span> build_product_properties<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>Awesome, now <code>product_properties</code> is built automatically in case it doesn&#8217;t exist. We still have the method accessing issue though. For that I used <code>method_missing</code>.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">included</span><span style="color:#006600; font-weight:bold;">&#40;</span>base<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#9900CC;">alias_method_chain</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:autobuild</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> product_properties_with_autobuild<br />
&nbsp; &nbsp; &nbsp; product_properties_without_autobuild <span style="color:#006600; font-weight:bold;">||</span> build_product_properties<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> product_properties.<span style="color:#9900CC;">public_methods</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>meth.<span style="color:#5A0A0A; font-weight:bold;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; product_properties.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">super</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>Now if a method is missing from Tee or Pen instance it will be delegated to <code>product_properties</code>, which enables us to use <code>@tee.price</code> and <code>@tee.title</code>.</p>

<p>However, what about validations? Let&#8217;s say we want all products to always have a title, and we want to see an error appear on a Tee instance when <code>ProductProperties#title</code> is missing. Basically I want to completely remove product_properties from my sight as if it doesn&#8217;t exist, make it absolutely transparent. Let&#8217;s add the necessary validation in ProductProperties.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> ProductProperties <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:polymorphic</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> :<span style="color:#5A0A0A; font-weight:bold;">destroy</span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">validates_presence_of</span> <span style="color:#ff3333; font-weight:bold;">:title</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>And now let&#8217;s make all Sellable models respect the validation as if it&#8217;s their own.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">included</span><span style="color:#006600; font-weight:bold;">&#40;</span>base<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">validate</span> <span style="color:#ff3333; font-weight:bold;">:product_properties_must_be_valid</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#9900CC;">alias_method_chain</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:autobuild</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> product_properties_with_autobuild<br />
&nbsp; &nbsp; &nbsp; product_properties_without_autobuild <span style="color:#006600; font-weight:bold;">||</span> build_product_properties<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> product_properties.<span style="color:#9900CC;">public_methods</span>.<span style="color:#9966CC; font-weight:bold;">include</span>?<span style="color:#006600; font-weight:bold;">&#40;</span>meth.<span style="color:#5A0A0A; font-weight:bold;">to_s</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; product_properties.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">super</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; protected<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> product_properties_must_be_valid<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> product_properties.<span style="color:#9900CC;">valid</span>?<br />
&nbsp; &nbsp; &nbsp; &nbsp; product_properties.<span style="color:#5A0A0A; font-weight:bold;">errors</span>.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>attr, message<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">errors</span>.<span style="color:#5A0A0A; font-weight:bold;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span>attr, message<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>Notice that I&#8217;m including an additional validator with the Sellable module. The validator collects all the errors on ProductProperties and adds them to parent class as if the errors are on a Tee or Pen itself.</p>

<p>As a nice finishing touch we can put this snippet into a Rails initializer.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">acts_as_product</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#008000; font-style:italic;"># now we can say</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Tee <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; acts_as_product<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>Although that&#8217;s a matter of taste.</p>

<h2>Fixing method_missing</h2>

<p>There is a problem with method&#95;missing. It checks the array of public&#95;methods on product&#95;properties to find out if delegation should occur. This check will fail in cases like <code>@tee.title_changed?</code>. That&#8217;s a magic method and therefore will not be part of static method array. Well, this is an easy fix.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#008000; font-style:italic;"># Replace old method_missing with this one:</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; product_properties.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">NoMethodError</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">super</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>As you can see, even magic methods will work this way. Only if a <code>NoMethodError</code> is thrown we withdraw back into <code>super</code>.</p>

<h2>Handling attributes hash</h2>

<p>In the comments Austin brought up a case where initializing new models like <code>Tee.new(:title =&gt; "foo")</code> will throw an unknown attribute error. That&#8217;s expected since we rely on <code>method_missing</code> for accessing ProductProperties attributes. Instead we should define accessor methods explicitly in our individual products. Thankfully, it&#8217;s not too hard to accomplish with our Sellable mixin. First we need to add a submodule <code>ClassMethods</code> with a class method that uses class_eval to magically generate missing attributes.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> ClassMethods<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> define_product_properties_accessors<br />
&nbsp; &nbsp; &nbsp; all_attributes = ProductProperties.<span style="color:#9900CC;">content_columns</span>.<span style="color:#9900CC;">map</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:name<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; ignored_attributes = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;created_at&quot;</span>, <span style="color:#996600;">&quot;updated_at&quot;</span>, <span style="color:#996600;">&quot;sellable_type&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; attributes_to_delegate = all_attributes <span style="color:#006600; font-weight:bold;">-</span> ignored_attributes<br />
&nbsp; &nbsp; &nbsp; attributes_to_delegate.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>attrib<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; class_eval <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>RUBY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{attrib}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; product_properties.<span style="color:#008000; font-style:italic;">#{attrib}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{attrib}=(value)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">product_properties</span>.<span style="color:#008000; font-style:italic;">#{attrib} = value</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{attrib}?</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">product_properties</span>.<span style="color:#008000; font-style:italic;">#{attrib}?</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; RUBY<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>I&#8217;ll walk through this code quickly. First we&#8217;re extracting only the columns that we want to access. When we call <code>content_columns</code> in the first line of the method, it already excludes a bunch of special columns such as <code>id</code> and <code>type</code>. We then manually subtract more columns we&#8217;d like to ignore, such as timestamps, and polymorphic type.</p>

<p>Next we iterate over each remaining attribute and creating instance methods for it, such as <code>title</code>, <code>title=</code> and (for completeness) <code>title?</code>. Having these accessors defined explicitly is enough for ActiveRecord to see them when performing mass assignment, etc. We can now do something like <code>Tee.new(:title =&gt; "foo")</code> without any problems. The extra cases such as <code>@tee.title_changed?</code> are still handled by <code>method_missing</code> so we&#8217;re good.</p>

<p>One more thing left. We need to run this method on the base class into which we include Sellable. Just need to add a couple of lines to the <code>self.included</code> hook.</p>

<p><pre></pre></p>

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; def self.included(base)<br />
&nbsp; &nbsp; base.has_one :product_properties, :as =&gt; :sellable, :autosave =&gt; true<br />
&nbsp; &nbsp; base.validate :product_properties_must_be_valid<br />
&nbsp; &nbsp; base.alias_method_chain :product_properties, :autobuild<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; # Add these two lines:<br />
&nbsp; &nbsp; base.extend ClassMethods<br />
&nbsp; &nbsp; base.define_product_properties_accessors<br />
&nbsp; end</div></div>

<p></p>

<p>And we&#8217;re all set.</p>

<h2 id="mti-the-short-story">All together now</h2>

<p>Here&#8217;s the full picture of everything we just did.</p>

<p><pre></pre></p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">acts_as_product</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">include</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> ProductProperties <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:polymorphic</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span>, <span style="color:#ff3333; font-weight:bold;">:dependent</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> :<span style="color:#5A0A0A; font-weight:bold;">destroy</span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">validates_presence_of</span> <span style="color:#ff3333; font-weight:bold;">:title</span> <span style="color:#008000; font-style:italic;"># for example</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> Sellable<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">included</span><span style="color:#006600; font-weight:bold;">&#40;</span>base<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">has_one</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:as</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:sellable</span>, <span style="color:#ff3333; font-weight:bold;">:autosave</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#0000FF; font-weight:bold;">true</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#5A0A0A; font-weight:bold;">validate</span> <span style="color:#ff3333; font-weight:bold;">:product_properties_must_be_valid</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#9900CC;">alias_method_chain</span> <span style="color:#ff3333; font-weight:bold;">:product_properties</span>, <span style="color:#ff3333; font-weight:bold;">:autobuild</span><br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#9900CC;">extend</span> ClassMethods<br />
&nbsp; &nbsp; &nbsp; base.<span style="color:#9900CC;">define_product_properties_accessors</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> product_properties_with_autobuild<br />
&nbsp; &nbsp; &nbsp; product_properties_without_autobuild <span style="color:#006600; font-weight:bold;">||</span> build_product_properties<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> method_missing<span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; product_properties.<span style="color:#9900CC;">send</span><span style="color:#006600; font-weight:bold;">&#40;</span>meth, <span style="color:#006600; font-weight:bold;">*</span>args, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">rescue</span> <span style="color:#CC00FF; font-weight:bold;">NoMethodError</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">super</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">module</span> ClassMethods<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> define_product_properties_accessors<br />
&nbsp; &nbsp; &nbsp; &nbsp; all_attributes = ProductProperties.<span style="color:#9900CC;">content_columns</span>.<span style="color:#9900CC;">map</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">&amp;</span>:name<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; ignored_attributes = <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#996600;">&quot;created_at&quot;</span>, <span style="color:#996600;">&quot;updated_at&quot;</span>, <span style="color:#996600;">&quot;sellable_type&quot;</span><span style="color:#006600; font-weight:bold;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; attributes_to_delegate = all_attributes <span style="color:#006600; font-weight:bold;">-</span> ignored_attributes<br />
&nbsp; &nbsp; &nbsp; &nbsp; attributes_to_delegate.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>attrib<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; class_eval <span style="color:#006600; font-weight:bold;">&lt;&lt;-</span>RUBY<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{attrib}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; product_properties.<span style="color:#008000; font-style:italic;">#{attrib}</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{attrib}=(value)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">product_properties</span>.<span style="color:#008000; font-style:italic;">#{attrib} = value</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#008000; font-style:italic;">#{attrib}?</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">product_properties</span>.<span style="color:#008000; font-style:italic;">#{attrib}?</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; RUBY<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; protected<br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> product_properties_must_be_valid<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">unless</span> product_properties.<span style="color:#9900CC;">valid</span>?<br />
&nbsp; &nbsp; &nbsp; &nbsp; product_properties.<span style="color:#5A0A0A; font-weight:bold;">errors</span>.<span style="color:#5A0A0A; font-weight:bold;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>attr, message<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">errors</span>.<span style="color:#5A0A0A; font-weight:bold;">add</span><span style="color:#006600; font-weight:bold;">&#40;</span>attr, message<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Tee <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; acts_as_product<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> Pen <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#CC00FF; font-weight:bold;"><span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span></span><br />
&nbsp; &nbsp; acts_as_product<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p></p>

<p>This can be easily adapted for any other use case besides products in a store. In fact, with some meta magic or code generation this can easily be made into a plugin which I encourage you to try and send me the link when you&#8217;re done. :)</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/U3uFAuj6u8E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/multiple-table-inheritance-active-record/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/multiple-table-inheritance-active-record/</feedburner:origLink></item>
		<item>
		<title>Testing Helpers That Use Scoped Translations</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/4IO_6W_xYB4/</link>
		<comments>http://mediumexposure.com/testing-helpers-use-scoped-translations/#comments</comments>
		<pubDate>Mon, 02 Nov 2009 21:00:03 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[Update: While this technique is useful when you actually need to bind a template to your helper test, most of the time you can simply stub the helper right there, using something like stub(self).t('.title') { &#34;Title&#34; }

Once on a beautiful day the sun was shining and the room was full of pleasant warmth. I was [...]]]></description>
			<content:encoded><![CDATA[<p class="warning alert"><strong>Update:</strong> While this technique is useful when you actually need to bind a template to your helper test, most of the time you can simply stub the helper right there, using something like <code class="codecolorer text default"><span class="text">stub(self).t('.title') { &quot;Title&quot; }</span></code></p>

<p>Once on a beautiful day the sun was shining and the room was full of pleasant warmth. I was whistling a tune happily to myself while writing the following rails helper.</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> title<span style="color:#006600; font-weight:bold;">&#40;</span>page_title, show_title = <span style="color:#0000FF; font-weight:bold;">true</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">content_for</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#ff3333; font-weight:bold;">:title</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#123;</span> t<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'.title'</span>, <span style="color:#ff3333; font-weight:bold;">:default</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> page_title<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; &nbsp; <span style="color:#0066ff; font-weight:bold;">@show_title</span> = show_title<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>It&#8217;s so neat and simple. It allows you to write <code>title "English Title"</code> and provides a way to override title with translation scoped like <code>pages.index.title</code>.</p>

<p>Then came the test (apologies, TDD purists). Whistling along with the chirping birds I put the following in my helper test.</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test_helper'</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> LayoutHelperTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActionView::TestCase</span><br />
&nbsp; &nbsp; context <span style="color:#996600;">&quot;#title helper&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; should <span style="color:#996600;">&quot;create content for title&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; title<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;foobar&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">assert_equal</span> <span style="color:#996600;">&quot;foobar&quot;</span>, <span style="color:#0066ff; font-weight:bold;">@content_for_title</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>Suddenly the birds went silent. The room got colder and darker. I got an error.</p>

<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; NameError: undefined local variable or method `template' for #&lt;LayoutHelperTest:0x102e8ab40&gt;</div></div>

<p>Here&#8217;s what happened. Using scoped translations such as <code>t('.title')</code> requires a template. It makes perfect sense because scope can only be looked up for a particular template&#8217;s path. After some research I found that it&#8217;s quite easy to stub a template for tests to work. You can put something like this in your setup method.</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#008000; font-style:italic;"># Using RR (http://github.com/btakita/rr) for stubbing.</span><br />
&nbsp; <span style="color:#008000; font-style:italic;"># Easy to convert to equivalent in mocha/flexmock/etc.</span><br />
&nbsp; stub<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">template</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#6666ff; font-weight:bold;">ActionView::Template</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span> <span style="color:#996600;">&quot;app/views/index.html.haml&quot;</span> <span style="color:#006600; font-weight:bold;">&#125;</span></div></div>

<p>This is the kind of usefulness that could easily be made into a helper. You can put this in your test_helper.rb.</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#9966CC; font-weight:bold;">def</span> use_template<span style="color:#006600; font-weight:bold;">&#40;</span>path<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; stub<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#0000FF; font-weight:bold;">self</span><span style="color:#006600; font-weight:bold;">&#41;</span>.<span style="color:#9900CC;">template</span> <span style="color:#006600; font-weight:bold;">&#123;</span> <span style="color:#6666ff; font-weight:bold;">ActionView::Template</span>.<span style="color:#5A0A0A; font-weight:bold;">new</span> <span style="color:#CC00FF; font-weight:bold;">File</span>.<span style="color:#9900CC;">join</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;app&quot;</span>, <span style="color:#996600;">&quot;views&quot;</span>, path<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#006600; font-weight:bold;">&#125;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>Now my test looks very neat.</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; <span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'test_helper'</span><br />
<br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">class</span> LayoutHelperTest <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActionView::TestCase</span><br />
&nbsp; &nbsp; context <span style="color:#996600;">&quot;#title helper&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; setup <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; use_template <span style="color:#996600;">&quot;pages/index.html.haml&quot;</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<br />
&nbsp; &nbsp; &nbsp; should <span style="color:#996600;">&quot;create content for title&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; title<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">&quot;foobar&quot;</span><span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color:#5A0A0A; font-weight:bold;">assert_equal</span> <span style="color:#996600;">&quot;foobar&quot;</span>, <span style="color:#0066ff; font-weight:bold;">@content_for_title</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>Running tests&#8230; Green! And birds are back!</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/4IO_6W_xYB4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/testing-helpers-use-scoped-translations/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/testing-helpers-use-scoped-translations/</feedburner:origLink></item>
		<item>
		<title>Off Github</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/wdVhI49e98Q/</link>
		<comments>http://mediumexposure.com/github/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 16:36:10 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[Right about now everyone is switching away from GitHub gem host. It&#8217;s crappy enough that you have to edit environments in your config files — you also have to reinstall the big pile of gems on your machines. Cleaning up my big old gem list doesn&#8217;t strike me as a fun leisure time.

Off Github is [...]]]></description>
			<content:encoded><![CDATA[<p>Right about now everyone is switching away from <a href="http://gems.github.com">GitHub gem host</a>. It&#8217;s crappy enough that you have to edit environments in your config files — you also have to reinstall the big pile of gems on your machines. Cleaning up my big old gem list doesn&#8217;t strike me as a fun leisure time.</p>

<p><a href="http://github.com/maxim/off_github">Off Github</a> is there to make this process less painful. Run it on the machines where you have gems installed and it will help you get rid of github legacy.</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/wdVhI49e98Q" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/github/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/github/</feedburner:origLink></item>
		<item>
		<title>Drier gem configs</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/P1RqNqCwDgE/</link>
		<comments>http://mediumexposure.com/drier-gem-configs/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 22:32:12 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[obsolete]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[Update: This article is obsolete. Gemcutter should take first place in your gem sources. This way there is no reason to use :source option at all.

Now is the worst time for duplication in gem configs with all the changes going on. GitHub is not a gem host anymore. Soon RubyForge may follow the same path.

with_options [...]]]></description>
			<content:encoded><![CDATA[<p class="warning alert"><strong>Update:</strong> This article is obsolete. Gemcutter should take first place in your gem sources. This way there is no reason to use :source option at all.</p>

<p>Now is the worst time for duplication in gem configs with all the changes going on. <a href="http://github.com">GitHub</a> is not a gem host anymore. Soon <a href="http://rubyforge.org">RubyForge</a> may follow the same path.</p>

<p><code class="codecolorer text default"><span class="text">with_options</span></code> provides a perfect way to minimize this duplication. I personally forgot it even existed until now. Watch how this mess:</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;settingslogic&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span><br />
&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;authlogic&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span><br />
&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;compass&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span><br />
&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;will_paginate&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span><br />
&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;inherited_resources&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span><br />
&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;haml&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span></div></div>

<p>becomes dry</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; config.<span style="color:#9900CC;">with_options</span> <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gemcutter.org&quot;</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>c<span style="color:#006600; font-weight:bold;">|</span><br />
&nbsp; &nbsp; c.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;settingslogic&quot;</span><br />
&nbsp; &nbsp; c.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;authlogic&quot;</span><br />
&nbsp; &nbsp; c.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;compass&quot;</span><br />
&nbsp; &nbsp; c.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;will_paginate&quot;</span><br />
&nbsp; &nbsp; c.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;inherited_resources&quot;</span><br />
&nbsp; &nbsp; c.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;haml&quot;</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p><strong>Update:</strong> Forgot to mention that you need to <code class="codecolorer text default"><span class="text">require &quot;active_support&quot;</span></code> in order for this to work in tests, etc. Thanks daeltar in comments.</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/P1RqNqCwDgE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/drier-gem-configs/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/drier-gem-configs/</feedburner:origLink></item>
		<item>
		<title>My Tools of the Trade</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/q7j9dGZjlwg/</link>
		<comments>http://mediumexposure.com/my-tools-trade/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 02:00:54 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[concepts]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[I used to be somewhat settled, living my stationary life in a Brooklyn apartment. Circumstances have changed in 2009, when I started to spend a lot of time on the go. This was the point at which all of the commitments, contracts, and physical commodities I had been piling up over the years have emerged [...]]]></description>
			<content:encoded><![CDATA[<p>I used to be somewhat settled, living my stationary life in a Brooklyn apartment. Circumstances have changed in 2009, when I started to spend a lot of time on the go. This was the point at which all of the commitments, contracts, and physical commodities I had been piling up over the years have emerged in the form of monumental pain. It felt like a greasy, sticky pile of goo keeping me in place. There were car lease, apartment rent, phone contract to name a few. Each one is very costly to terminate.  Above realizations have effectively changed the way I think. What used to be a passive crawl towards comfort-in-the-goo has now morphed into an active strive to achieve compactness and simplicity. A strive for &#8220;life in a backpack&#8221; if you will.</p>

<p>Certainly these changes have reflected on my tools of trade.</p>

<h2>Backpack</h2>

<p><img src="http://dl.getdropbox.com/u/2274503/tools_of_trade/backpack.jpg" alt="backpack" title=""/></p>

<ul>
<li><p>Incase backpack </p>

<p>I had to search through half Manhattan for it (urgent at that moment). It fits everything I need to carry, which is essentially everything I listed here shy of the &#8220;Stationary Hardware&#8221; section.</p></li>
</ul>

<h2>Mobile Hardware</h2>

<p><img src="http://dl.getdropbox.com/u/2274503/tools_of_trade/computers.jpg" alt="computers" title=""/></p>

<ul>
<li><p>Late 2007 17&#8221; MacBook Pro</p>

<p>It has 2.6Ghz Core 2 Duo, 4GB RAM, and 200GB 7200RPM HDD. I do vast majority of the work on it.</p></li>
<li><p>Acer Aspire One</p>

<p>My &#8220;backup&#8221; computer (with 16Gb SSD and 16Gb SD card) running both WinXP and <a href="http://www.canonical.com/projects/ubuntu/unr">Ubuntu Netbook Remix</a>. I use it primarily for leisure as I happen to be a fan of pre-2004 computer RPGs and strategies which netbooks are perfect for. Acer is good for programming too, since it sports an incredible 9hr battery which is perfect for long travels (although most would hate the small size constraint.)</p></li>
<li><p><a href="http://www.amazon.com/Logitech-Optical-Notebook-Mouse-Plus/dp/B0001LTT5K">Logitech Optical Notebook Mouse Plus</a></p>

<p>When it comes to mouse, I never understood wireless. Mouse is not a remote control, you only use it close to the screen, so why care about batteries or recharging? For me it&#8217;s just extra mental/physical weight. Therefore my choice is this neat, wire-wrapping simple mouse.</p></li>
<li><p>iPhone 3G</p></li>
<li>Nintendo DS</li>
</ul>

<h2>Stationary Hardware</h2>

<p>Since I had some hardware accumulated over the years, and getting rid of it all wouldn&#8217;t make sense, I keep a couple of things in places where I spend most of the time. Mostly it comes down to the following two:</p>

<ul>
<li><p>24&#8221; Samsung monitor</p>

<p>Located at <a href="http://attic.mediumexposure.com/data/island_workspace.jpg">one of my destinations</a>.</p></li>
<li><p><a href="http://www.overclockersclub.com/reviews/freeagent_pro_1tb/">1TB Seagate FreeAgent Pro</a> HDD</p>

<p>Stationed at another location. I use it for time machine backups.</p></li>
</ul>

<h2>Misc</h2>

<p><img src="http://dl.getdropbox.com/u/2274503/tools_of_trade/misc.jpg" alt="misc" title=""/></p>

<p>In this small pocket I keep all kinds of misc SD cards, USB thumb drives, and DS games.</p>

<p><img src="http://dl.getdropbox.com/u/2274503/tools_of_trade/sketchbooks.jpg" alt="sketchbooks" title=""/></p>

<ul>
<li><a href="http://www.moleskines.com/klmrl717.html">Moleskine sketchbook</a> — I&#8217;m not a proponent of using Balsamiq or other wireframe solutions, todo, or time management software. Instead I prefer a small sketchbook (notes and small drawings), a big sketchbook (wire-framing, mind-mapping), and a pencil. I like that particular linked sketchbook because IMHO reporter-style is more comfortable than normal book-style. Besides, I hate any kind of grid on the pages, hence plain.</li>
</ul>

<h2>Software</h2>

<ul>
<li><p><a href="http://firefox.com">Firefox</a> — I use it with (and because of) following extensions.</p>

<ul>
<li><a href="http://agilewebsolutions.com/products/1Password">1Password</a> — no more looking for wallet, and no more reusing of the same password.</li>
<li><a href="http://adblockplus.org/en/">Adblock Plus</a> — block ads (duh).</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/1027">All-in-One Sidebar</a> — replaces all the meddling firefox popups (downloads/extensions/history panels) with a neat sidebar.</li>
<li><a href="http://www.customizegoogle.com/">CustomizeGoogle</a> — tons of Google search customizations.</li>
<li><a href="http://www.downloadhelper.net/">DownloadHelper</a> — because sometimes online flash players suck.</li>
<li><a href="http://getfirebug.com/">Firebug</a> — ultimate front-end debugger.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/5791">Flagfox</a> — I always found it fun to know in which country a website is hosted.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/189">GooglePreview</a> — helps browse results and quickly know what to expect.</li>
<li><a href="https://addons.mozilla.org/firefox/addon/2036">Server Spy</a> — quick and convenient way to know which server is running on visited websites. One more curiosity satisfier.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/5447">Tab Kit</a> — primary reason I&#8217;m sticking with Firefox. When you have > 30 tabs open at a time, and you&#8217;re using widescreen — vertical tabs are the way to go. Additionally, this plugin also does nesting and coloring which is incredibly useful for relating tabs to one-another (ie: links opened from this blog post will appear in tabs nested under the post&#8217;s tab).</li>
<li><a href="http://labs.mozilla.com/ubiquity/">Ubiquity</a> — this extension contains tons of awesomeness &#8211; you better see their screencast. However, I primarily use it as QuickSilver of Firefox. Opt+Space, type some words from the needed tab, Enter, the tab focuses. Incredibly useful when you have >30 tabs open.</li>
<li><a href="https://addons.mozilla.org/en-US/firefox/addon/60">Web Developer</a> — mostly for &#8220;disable cache&#8221; feature, different enable/disable shortcuts for javascript, css, etc, and cleaning cookies.</li>
<li><a href="http://www.xmarks.com/">XMarks</a> — former Foxmarks for bookmark sync across browsers and computers.</li>
<li><a href="http://developer.yahoo.com/yslow/">YSlow</a> — a treasure chest of optimization tips and benchmarks for improving site performance.</li>
</ul></li>
<li><p><a href="http://macromates.com">TextMate</a> — This is my code editor of choice. I also recently got interested in vim, and have been learning it, but haven&#8217;t really gotten comfortable enough to use it for most tasks.</p></li>
<li><p><a href="http://www.newsgator.com/INDIVIDUALS/NETNEWSWIRE/">NetNewsWire</a> — This is a great RSS reader which syncs with Google Reader as well as its complementary iPhone app. Definitely my favorite.</p></li>
<li><p><a href="http://wiki.github.com/koroshiya1/pwitter">Pwitter</a> — I&#8217;m not a heavy twitterer. I want a simple, resource-friendly mac client which works with growl and has all basic features. Pwitter has met and exceeded (in a good way) everything I wanted from a twitter client. I think it&#8217;s pretty underestimated.</p></li>
<li><p><a href="http://www.mozillamessaging.com/en-US/thunderbird/early_releases/">Thunderbird 3</a> — this is my shaky ground right now. I grew tired of how primitive Mail.app is. At the same time, I can&#8217;t keep gmail.com open. It runs flash which keeps crashing my browser under Snow Leopard. I was pleasantly surprised by the new features of Thunderbird 3. Among other additions, Mozilla taught it to speak the Gmail language (archiving, all mail, etc). This wasn&#8217;t the case in previous versions, which I disliked. It also serves as a great newsgroups reader, which I use to read <a href="http://groups.google.com/group/comp.lang.ruby">comp.lang.ruby</a>.</p></li>
<li><p>Terminal — this is another treasure chest of irreplaceable tools some of which have existed since Unix inception.</p></li>
<li><p><a href="http://www.apple.com/itunes/">iTunes</a> — helps me stay updated with podcasts such as <a href="http://railscasts.com">Railscasts</a>, <a href="http://railsenvy.com">RailsEnvy</a>, and <a href="http://ruby5.envylabs.com/">Ruby5</a>.</p></li>
<li><p><a href="http://gitx.frim.nl/">GitX</a> — Awesome git browser for mac with some repo-manipulating capabilities. However, I mostly use it for its staging convenience. Sometimes I do too much at once. GitX provides very convenient GUI to split all the unstaged mess into separate neat commits.</p></li>
<li><p><a href="https://www.photoshop.com/">Photoshop</a> — I&#8217;ve become quite comfortable with photoshop. Use it for any non-batch image tasks.</p></li>
<li><p><a href="http://cyberduck.ch/">Cyberduck</a> — this is my sftp client of choice. It&#8217;s free and works well for me.</p></li>
<li><p><a href="http://getdropbox.com">Dropbox</a> — great for quick file upload/sync/backup. Pics for this blog post were taken on iPhone, synced through dropbox, and are linked directly from there.</p></li>
<li><p><a href="http://www.apple.com/macosx/what-is-macosx/mail-ical-address-book.html">iCal</a> — I tend to use reminders a lot. I also keep track of bills and projects this way. However, I prefer my physical notepad for daily goals.</p></li>
<li><p><a href="http://blacktree.com/">QuickSilver</a> — this is definitely my Swiss Army Knife. Irreplaceable for navigation and file operations.</p></li>
<li><p><a href="http://www.ironstarmedia.co.uk/osx-image-resizer/">ImageResizer</a> — convenient little tool for batch image resizing.</p></li>
<li><p>Communication</p>

<ul>
<li><a href="http://www.skype.com/download/skype/macosx/">Skype</a> — I work remotely a lot as you can imagine.</li>
<li><a href="http://adium.im">Adium</a> — looks like the best AOL/ICQ/YIM/MSN/GTK mac client out there.</li>
<li><a href="http://limechat.net/mac/">LimeChat</a> &#8211; I used to like Colloquy, but its resource-hogging habits forced me to look for better alternatives. So far this has been incredibly nice and lightweight sporting all the features I need in an IRC client.</li>
</ul></li>
</ul>

<h2>Hosting</h2>

<ul>
<li><a href="http://dreamhost.com/">Dreamhost</a> — this is my sandbox environment. I don&#8217;t use it for anything but hosting this blog and some personal side-projects. The occasional bumpy service is justified by the price though.</li>
<li><a href="http://webfaction.com/">WebFaction</a> — a very easy-to-use, affordable, and incredibly fast/stable shared hosting. Currently runs two projects (<a href="http://scripteka.com">Scripteka</a> and <a href="http://wehike.net">Wehike</a>) on one account without any problems.</li>
<li><a href="http://linode.com">Linode</a> — our first stage heavy-weight. If an app is expected to have any significant load, this is where we start developing.</li>
<li><a href="http://www.turnkeyinternet.net/">Turnkey Internet</a> — we use this for dedicated servers because they seem to be the most affordable while having well-performing network. However, most of sysadmin burden goes on your shoulders. There are options with more support, but they aren&#8217;t cheap.</li>
<li><a href="http://heroku.com">Heroku</a> — lately this is the place I go for my personal Rails projects. The deployment strategy there is pretty freaking incredible.</li>
</ul>

<p>Simplifying and compacting your life is not easy. I mostly try to have fewer tools covering broader range of tasks. This helps portability and keeps me sane. As opposed to <a href="http://afreshcup.com/2009/10/11/my-tools-of-the-trade-2009/">Mike Gunderloy&#8217;s Tools of Trade</a> my set tends to have very little overlap in functionality. Single image editor, single organizational tool, etc. Interestingly, I don&#8217;t  actively pursue this concept. I just don&#8217;t feel the need for more yet. Surely this list will expand in the future.</p>

<p>This post was inspired by <a href="http://afreshcup.com/2009/10/11/my-tools-of-the-trade-2009/">Mike Gunderloy&#8217;s Tools of Trade</a>. I&#8217;d like to join him in encouraging you to write your own &#8220;Tools of Trade&#8221; post.</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/q7j9dGZjlwg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/my-tools-trade/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/my-tools-trade/</feedburner:origLink></item>
		<item>
		<title>Rake script for managing Rails plugins with Git submodules</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/NezkusYp6Cg/</link>
		<comments>http://mediumexposure.com/rake-script-managing-rails-plugins-git-submodules/#comments</comments>
		<pubDate>Sat, 12 Sep 2009 18:47:59 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[Problem with gitmodules and rails plugins

Submodules aren&#8217;t very easy. You have to know a few things before messing with them. When installing you have to follow a bunch of steps in order to get them properly registered within git. Uninstalling is even sadder. You need to manually edit a couple of git config files, and [...]]]></description>
			<content:encoded><![CDATA[<h2>Problem with gitmodules and rails plugins</h2>

<p>Submodules aren&#8217;t very easy. You have to know a few things before messing with them. When installing you have to follow a bunch of steps in order to get them properly registered within git. Uninstalling is even sadder. You need to manually edit a couple of git config files, and perform some more git operations.  When dealing with Rails plugins &#8211; you should also remember to check if plugin contains an install.rb/uninstall.rb hook and run them manually. This is enough repetitive crap for me to justify some automation.</p>

<h2>Solution: Automation with Rake</h2>

<p>Note: <strong>This solution is specifically for rails plugins hosted on <a href="http://github.com">github</a>.</strong></p>

<p>When I think <em>automation</em> in the context of Rails &#8211; I immediately think <strong>rake</strong>. Without further ado I present <a href="http://gist.github.com/185746">a rake script</a> which takes care of all the aforementioned problems for you.</p>

<ul>
<li>Automated module install &#8211; no need to run any git commands.</li>
<li>Automated module uninstall &#8211; no need to edit git config files by hand.</li>
<li>Automated running of install.rb/uninstall.rb plugin hooks.</li>
<li>Automated module updates.</li>
<li>Automatically uses github.</li>
</ul>

<p>The usage is as simple as it gets. Read comments on top for list of available tasks.</p>

<p class="download">Grab it here: <a href="http://gist.github.com/185746">http://gist.github.com/185746</a></p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/NezkusYp6Cg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/rake-script-managing-rails-plugins-git-submodules/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/rake-script-managing-rails-plugins-git-submodules/</feedburner:origLink></item>
		<item>
		<title>Getting Rails 2.3.3 and Mocha &gt;=0.9.6 to play nice with Test::Unit and Shoulda</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/bt-gReIHqL0/</link>
		<comments>http://mediumexposure.com/getting-rails-233-and-mocha-096-play-nice-testunit-and-shoulda/#comments</comments>
		<pubDate>Sun, 02 Aug 2009 14:59:33 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[Simultaneous changes in Rails 2.3.3 and Mocha &#62;=0.9.6 have caused some headaches in test::unit (or shoulda) tests. In my case I saw anomalies such as expectations persisting across tests. You put expects(:foo).never in test A and get &#8220;unsatisfied expectation&#8221; failure in test B where you happen to call :foo. This is due to unfortunate dependency [...]]]></description>
			<content:encoded><![CDATA[<p>Simultaneous changes in Rails 2.3.3 and Mocha &gt;=0.9.6 have caused some headaches in test::unit (or shoulda) tests. In my case I saw anomalies such as expectations persisting across tests. You put expects(:foo).never in test A and get &#8220;unsatisfied expectation&#8221; failure in test B where you happen to call :foo. This is due to unfortunate dependency on load order which could cause runner logic to be erroneously overridden. Here&#8217;s the steps you need to take to tidy up this setup to make sure it works correctly.</p>

<h3>Update mocha to &gt;= 0.9.7</h3>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; ~<span style="color: #000000; font-weight: bold;">%</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> gem update mocha</div></div>

<h3>Install test-unit gem</h3>

<div class="codecolorer-container bash default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; ~<span style="color: #000000; font-weight: bold;">%</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> gem <span style="color: #c20cb9; font-weight: bold;">install</span> test-unit</div></div>

<h3>Don&#8217;t load mocha yourself</h3>

<p>If you had anything like this line in your test environment, <span class="caps">REMOVE IT</span>.</p>

<p><del><code class="codecolorer text default"><span class="text">config.gem &quot;mocha&quot;</span></code></del></p>

<h3>Ensure correct load order</h3>

<p>If using Shoulda, make sure your test.rb environment loads test-unit before shoulda.</p>

<div class="codecolorer-container rails default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="rails codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;test-unit&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;test/unit&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;&gt;=2.0.3&quot;</span> <br />
&nbsp; config.<span style="color:#9900CC;">gem</span> <span style="color:#996600;">&quot;thoughtbot-shoulda&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:lib</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;shoulda&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:source</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;http://gems.github.com&quot;</span>, <span style="color:#ff3333; font-weight:bold;">:version</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#996600;">&quot;&gt;=2.10.1&quot;</span></div></div>

<p>This should hopefully fix mocha issues with rails 2.3.3.</p>

<p>For more explanation check out <a href="http://groups.google.com/group/mocha-developer/browse_thread/thread/bd76e2f0ec28459a">this message</a> on mocha&#8217;s mail list and <a href="https://rails.lighthouseapp.com/projects/8994/tickets/2858">this lighthouse ticket</a>.</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/bt-gReIHqL0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/getting-rails-233-and-mocha-096-play-nice-testunit-and-shoulda/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/getting-rails-233-and-mocha-096-play-nice-testunit-and-shoulda/</feedburner:origLink></item>
		<item>
		<title>Avoiding nested blocks</title>
		<link>http://feedproxy.google.com/~r/mediumexposure/~3/V0xEDrkAWEo/</link>
		<comments>http://mediumexposure.com/avoiding-nested-blocks/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 05:48:32 +0000</pubDate>
		<dc:creator>hakunin</dc:creator>
				<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[solutions]]></category>

		<guid isPermaLink="false" />
		<description><![CDATA[Today I had to silence some output streams so that messages don&#8217;t pollute the STDOUT. I used the silence_stream method built into Rails, described well in this article.

&#160; silence_stream&#40;STDOUT&#41; do
&#160; &#160; # ...my code...
&#160; end

Very nice, except I also wanted to filter STDERR output. Not a problem.

&#160; silence_stream&#40;STDOUT, STDERR&#41; do
&#160; &#160; # ...my code...
&#160; end

Well, [...]]]></description>
			<content:encoded><![CDATA[<p>Today I had to silence some output streams so that messages don&#8217;t pollute the <span class="caps">STDOUT</span>. I used the <code class="codecolorer text default"><span class="text">silence_stream</span></code> method built into Rails, described well in <a href="http://www.misuse.org/science/2007/08/01/suppressing-output-in-rubyrails/">this article</a>.</p>

<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; silence_stream<span style="color:#006600; font-weight:bold;">&#40;</span>STDOUT<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># ...my code...</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>Very nice, except I also wanted to filter <span class="caps">STDERR</span> output. Not a problem.</p>

<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; silence_stream<span style="color:#006600; font-weight:bold;">&#40;</span>STDOUT, STDERR<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># ...my code...</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>Well, shit. Here I got a &#8220;too many arguments&#8221; error. So it doesn&#8217;t support multiple streams. I guess it wants me to be ugly.</p>

<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; silence_stream<span style="color:#006600; font-weight:bold;">&#40;</span>STDOUT<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; silence_stream<span style="color:#006600; font-weight:bold;">&#40;</span>STDERR<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># ...my code...</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>I personally don&#8217;t take kindly this level of suckiness around here. I want example #2 to work. Well, after lighting some candles and praying to the Ruby gods, I came up with a scary implementation. In fact it&#8217;s so spooky that it may have the same effect as glancing at the <a href="http://en.wikipedia.org/wiki/The_Mexican_Staring_Frog_of_Southern_Sri_Lanka">Mexican Starting Frog of Southern Sri Lanka</a>. You may then throw a chair at me on the Jerry Springer show, so I rather not show it to you.</p>

<p>However, after having cleansed my .rb file with some broc flowers and xander roots I came up with a better solution. Recursion is the key. See if you can understand what is happening.</p>

<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color:#9966CC; font-weight:bold;">def</span> silence_streams<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>streams, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; silence_stream<span style="color:#006600; font-weight:bold;">&#40;</span>streams.<span style="color:#9900CC;">pop</span><span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">if</span> streams.<span style="color:#9900CC;">empty</span>?<br />
&nbsp; &nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">yield</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">else</span><br />
&nbsp; &nbsp; &nbsp; silence_streams<span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#006600; font-weight:bold;">*</span>streams, <span style="color:#006600; font-weight:bold;">&amp;</span>blk<span style="color:#006600; font-weight:bold;">&#41;</span><br />
&nbsp; &nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span><br />
<span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>This is a basic use of recursion, which is not immediately clear when dealing with nested Ruby blocks. When multiple streams are passed in I&#8217;m popping out the last stream and silencing it alone, then calling the same method with the remaining streams. This is happening until only one stream left to silence. The last one gets silenced with the original block passed in, which means that the original block is executed at the deepest nesting level, where all passed streams are silenced. As a result I got this much desired functionality without resorting to eval, yay.</p>

<div class="codecolorer-container ruby default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;"><div class="ruby codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; silence_streams<span style="color:#006600; font-weight:bold;">&#40;</span>STDOUT, STDERR<span style="color:#006600; font-weight:bold;">&#41;</span> <span style="color:#9966CC; font-weight:bold;">do</span><br />
&nbsp; &nbsp; <span style="color:#008000; font-style:italic;"># ...my code...</span><br />
&nbsp; <span style="color:#9966CC; font-weight:bold;">end</span></div></div>

<p>There we go. This solution can be applied to cases where you&#8217;d rather avoid overriding stuff (thus keeping out of method implementation details).</p>

<p>
<strong>Update:</strong> Made recursion more concise thanks to apeiros on #railsbridge.</p>
<img src="http://feeds.feedburner.com/~r/mediumexposure/~4/V0xEDrkAWEo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://mediumexposure.com/avoiding-nested-blocks/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://mediumexposure.com/avoiding-nested-blocks/</feedburner:origLink></item>
	</channel>
</rss>
