<?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:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Virtuous Code</title>
	
	<link>http://avdi.org/devblog</link>
	<description>"...the three great virtues of a programmer: laziness, impatience, and hubris." -- Larry Wall</description>
	<lastBuildDate>Thu, 29 Oct 2009 15:06:10 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/VirtuousCode" type="application/rss+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Simplicity is Complicated</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/79qSI0Wxy4c/</link>
		<comments>http://avdi.org/devblog/2009/10/29/simplicity-is-complicated/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 14:00:57 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[philosophy]]></category>
		<category><![CDATA[simplicity]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=291</guid>
		<description><![CDATA[The favorite rhetorical fallback of politicians of every stripe is &#8220;it&#8217;s for the children&#8221;.  Anything can be justified in terms of making things better for children if you frame it right.  Lately I&#8217;ve begun to think that the word &#8220;simple&#8221; is the programmer&#8217;s version of &#8220;for the children&#8221;. We use it to justify [...]]]></description>
			<content:encoded><![CDATA[<p>The favorite rhetorical fallback of politicians of every stripe is &#8220;it&#8217;s for the children&#8221;.  Anything can be justified in terms of making things better for children if you frame it right.  Lately I&#8217;ve begun to think that the word &#8220;simple&#8221; is the programmer&#8217;s version of &#8220;for the children&#8221;. We use it to justify all manner of decisions.</p>

<p>I&#8217;m not excepting myself, either. I see myself doing this all the time. &#8220;It&#8217;ll make things simple&#8221;, I say. Which by a strict interpretation is true. Whatever direction I&#8217;m advocating, it usually makes [some] things simple. It usually also makes other things more complicated.</p>

<p>Let&#8217;s look at an example of two opposing kinds of simplicity.  My old boss <a href="http://japhr.blogspot.com/2009/10/newbie-feedback.html">Chris Strom recently wrote about some common Ruby newbie mistakes</a> (it&#8217;s a great article, you should read the whole thing). Here is an example he gave of code written by someone new to the Ruby language:</p>



<pre name="code" class="ruby">
sum = 0
i = 0
while i &lt; times.length
  time = times[i]
  # parse / manipulate the time
  sum = sum + time
  i = i + 1
end
</pre>



<p>After several iterations of successively introducing Ruby idioms and features, the code looked like this:</p>

</pre>

<pre name="code" class="ruby">
def average_time_of_day(times)
  sum = times.map(&amp;:to_time).inject(&amp;:+)
end
</pre>



<p>Which example is simpler? Well, that depends on what you mean by "simple". As Chris points out, the latter example is much closer to the domain. The line <code>sum = times.map(&amp;:to_time).inject(&amp;:+)</code> neatly expresses the intent of the code without getting bogged down too much in implementation. It's also more concise.</p>

<p>On the other hand, the first example uses language constructs that are familiar to almost all programmers, not just Ruby programmers. It is simpler in the sense that even someone who has only basic programming skills could probably work their way through it, without needing to understand concepts like <code>#inject</code> and symbol-to-proc.</p>

<p>What do we mean when we say the word "simple"? I've realised that we programmers use "simple" to mean a lot of different things. Some of the ways we use the word "simple" include:</p>

<p><strong>Minimizing unnecessary effort.</strong> Characterised by the classic admonition to "Keep It Simple, Stupid". Or as the XP folks say, "<a href="http://c2.com/xp/DoTheSimplestThingThatCouldPossiblyWork.html">do the simplest thing that could possibly work</a>". Of course, sometimes when you choose to do less you force someone else to do more. And sometimes that someone else is you, two weeks down the road.</p>

<p><strong>Hiding complexity.</strong> <a href="http://rubyonrails.org/">Ruby on Rails</a> made web development simple, relative to tools that came before it. It accomplished this feat by embracing "convention over configuration". In order to do this, it had to incorporate a great deal of extra complexity in the form of algorithms which guess the intent of the programmer instead of forcing her to specify her wishes explicitly. Anyone using it eventually has to become familiar with these hidden rules in order to understand why Rails behaves the way it does.</p>

<p><strong>Avoiding difficult-to-understand features. </strong>In the name of simplicity, <a href="http://www.joelonsoftware.com/items/2009/09/23.html">some programmers advocate avoiding "magic" language features</a> they see as complicated and difficult, such as generics, recursion, or metaprogramming. Other coders say <a href="http://gilesbowkett.blogspot.com/2009/07/do-you-believe-in-magic.html">there is no such thing as magic</a> if you have an adequate understanding of the language, and that arbitrarily naming certain features "magical" is superstitious nonsense.</p>

<p><strong>Avoiding <a href="http://www.joelonsoftware.com/articles/fog0000000018.html">formal architecture</a>.</strong> There are programmers who feel that complexity is the inevitable result of spending too much time thinking about design, and that simple code is code that does it's job without being fastidiously decoupled and thoughtfully abstracted. Others say that this kind of thinking leads to an unmaintainable "<a href="http://www.laputan.org/mud/">big ball of mud</a>", the antithesis of simplicity.</p>

<p><strong>Elegance of design.</strong> Some insist that elegant orthoganality is what defines simplicity. <a href="http://www.faqs.org/docs/artu/ch01s06.html#id2877537">Simple components which do one thing well</a>, which have few interdependencies and can be composed into various configurations. Others retort that <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">all abstractions are leaky</a> and that trying to abstract the leaks away only complicates the job of solving real problems.</p>

<p><strong>Staying <a href="http://www.martinfowler.com/bliki/DomainSpecificLanguage.html">close to the domain</a>.</strong> To some, simplicity is ability to write code which looks like a plain-English explanation of the problem. But the underlying scaffolding which makes the code so understandable to a domain expert may be baroque and brittle in it's implementation.</p>

<p>Clearly, simplicity is not a simple subject.</p>

<p>I think the reason for this is the nature of complexity. Complexity is like an air pocket trapped under a layer of airtight plastic. If you push it down it just pops up somewhere else. Most of our attempts to "simplify" software really amount to pushing the complexity somewhere (or some-when) else. And our disagreements about what is meant by simplicity are really about where we think the complexity belongs. As a result, the goal of simplicity can be used to justify just about any course of action.</p>

<p>I challenge myself and anyone who reads this, next time you use the word "simple", to stop and think about what you mean by it. As an exercise, try to rephrase it in terms of where you are pushing the complexity. Let me know if you gain any insight from looking at it in this way.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=79qSI0Wxy4c:y_b4hEC0XBk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=79qSI0Wxy4c:y_b4hEC0XBk:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=79qSI0Wxy4c:y_b4hEC0XBk:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=79qSI0Wxy4c:y_b4hEC0XBk:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=79qSI0Wxy4c:y_b4hEC0XBk:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=79qSI0Wxy4c:y_b4hEC0XBk:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/79qSI0Wxy4c" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/29/simplicity-is-complicated/feed/</wfw:commentRss>
		<slash:comments>25</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/29/simplicity-is-complicated/</feedburner:origLink></item>
		<item>
		<title>Copying Amazon SimpleDB Domains</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/DM8kusrm3ws/</link>
		<comments>http://avdi.org/devblog/2009/10/28/copying-amazon-simpledb-domains/#comments</comments>
		<pubDate>Wed, 28 Oct 2009 14:00:36 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[boson]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[simpledb]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=285</guid>
		<description><![CDATA[Just a quickie today. Amazon SimpleDB has no built-in way to copy a domain &#8211; for the purposes of backing it up, for instance, or for populating a development domain with data from the production domain. Using the RightAws tools it&#8217;s pretty straightforward to implement domain copy, though:




  require 'progressbar'
  require 'right_aws'

  [...]]]></description>
			<content:encoded><![CDATA[<p>Just a quickie today. Amazon SimpleDB has no built-in way to copy a domain &#8211; for the purposes of backing it up, for instance, or for populating a development domain with data from the production domain. Using the <a href="http://rightaws.rubyforge.org/">RightAws</a> tools it&#8217;s pretty straightforward to implement domain copy, though:</p>



<pre name="code" class="ruby">
  require 'progressbar'
  require 'right_aws'

  def sdb_copy(source_domain, destination_domain)
    sdb = RightAws::SdbInterface.new
    sdb.list_domains do |results|
      domains = results[:domains]
      if domains.include?(destination_domain)
        raise &quot;Destination #{destination_domain} already exists&quot;
      end
    end
    sdb.create_domain(destination_domain)
    count = session.select(&quot;select count(*) from #{domain}&quot;)[:items].first[&quot;Domain&quot;][&quot;Count&quot;].first.to_i
    progress = ProgressBar.new('copy', count)
    sdb.select(&quot;select * from #{source_domain}&quot;) do |results|
      results[:items].each do |record|
        record.each_pair do |key, data|
          sdb.put_attributes(destination_domain, key, data)
          progress.inc
        end
      end
    end
    progress.finish
  end
</pre>



<p>This method has a few bells and whistles: it checks to see that the destination domain doesn&#8217;t already exist, and it displays a progress bar to let you know how far along the copy process is.</p>

<p>Unfortunately since SimpleDB doesn&#8217;t support any kind of bulk import the copies have to be made one by one, which is slooooow. A copy of about 45,000 items takes over 2 hours.</p>

<p>I&#8217;ve posted <a href="http://gist.github.com/220299">a Gist</a> with this method and a few other utilities for interacting with SimpleDB. It&#8217;s still in a pretty rough state, but it&#8217;s usable. If you use <a href="http://tagaholic.me/2009/10/14/boson-command-your-ruby-universe.html">Boson</a> you should be able to install it as a boson library with the following command:</p>



<pre name="code" class-"plain">
$ boson install http://gist.github.com/raw/220299/171c2b3c8aae955afa1dc38a78c77c0531e24d1c/simpledb.rb
</pre><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=DM8kusrm3ws:ONi55hI6nxc:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=DM8kusrm3ws:ONi55hI6nxc:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=DM8kusrm3ws:ONi55hI6nxc:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=DM8kusrm3ws:ONi55hI6nxc:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=DM8kusrm3ws:ONi55hI6nxc:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=DM8kusrm3ws:ONi55hI6nxc:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/DM8kusrm3ws" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/28/copying-amazon-simpledb-domains/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/28/copying-amazon-simpledb-domains/</feedburner:origLink></item>
		<item>
		<title>NullDB for DataMapper</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/WCvvnKTp6o4/</link>
		<comments>http://avdi.org/devblog/2009/10/27/nulldb-for-datamapper/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 14:00:29 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[nulldb]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=279</guid>
		<description><![CDATA[The first Ruby library I ever released, and still the one I get the most emails about, is NullDB. NullDB is an ActiveRecord database adapter which simply turns every database operation into a no-op. It is useful for speeding up tests which don&#8217;t rely on the database, as well as verifying that they are, in [...]]]></description>
			<content:encoded><![CDATA[<p>The first Ruby library I ever released, and still the one I get the most emails about, is <a href="http://nulldb.rubyforge.org/">NullDB</a>. NullDB is an ActiveRecord database adapter which simply turns every database operation into a no-op. It is useful for speeding up tests which don&#8217;t rely on the database, as well as verifying that they are, in fact, independent of the database.</p>

<p>Lately I&#8217;ve been working with <a href="http://datamapper.org/">DataMapper</a> and I&#8217;d begun to wonder how difficult it would be to write a DataMapper version of NullDB. As it turns out, the answer is &#8220;trivially easy&#8221;. In fact, it probably doesn&#8217;t even warrant making a library out of it &#8211; all the tools needed are right in the DataMapper distribution.</p>

<p>The task of a DataMapper null adapter is simplified in comparison to the ActiveRecord version by dint of DataMapper&#8217;s differing architecture. Where ActiveRecord scans the DB schema to extrapolate tables and columns, DataMapper makes the model classes the sole canonical source of schema information. This means that all the mucking about with schema.rb files that the original NullDB had to do is unnecessary.</p>

<p>The simplest form of a null database adapter is one that simply raises an exception every time code tries to touch the database. This kind of null backend is useful when you want to ensure that the software under test is completely isolated from the database. Rails Views are one example of code which you might want to keep rigidly database-independent in this fashion.</p>

<p>Setting up this type of null database backend in DataMapper is trivial:</p>



<pre name="code" class="ruby">
  DataMapper.setup(:default, &quot;abstract::&quot;)
</pre>



<p>This code uses the &#8220;abstract&#8221; adapter which comes with DataMapper. The Abstract adapter is primarily intended to provide a base class on which to build other adapters. But for our purposes it makes for a poor-man&#8217;s null database backend. Any attempt to write to or query from the database while this adapter is in effect will result in a NotImplementedError being raised:</p>



<pre name="code" class="ruby">
  p = Post.new(:title =&gt; &quot;NullDB for DataMapper&quot;)
  p.save # =&gt; NotImplementedError
</pre>



<p>What if we want to incoporate this technique into a complete test suite which includes both database-dependent and database-free tests? We need a way to make the null database active only while selected tests are being run. Once again, DataMapper&#8217;s design makes it easy to achieve our ends. DataMapper incorporates the concept of a  &#8220;repository stack&#8221;. instead of only having a single database adapter active for a whole session, or having different models tied to different adapters, DataMapper keeps a stack of adapter sessions in a stack. New sessions can be pushed onto the stack, and then popped off when they are no longer needed.</p>

<p>Here&#8217;s an example of how to set up a single Test::Unit test case to use a null database backend, while leaving other tests unaffected:</p>



<pre name="code" class="ruby">
class FooTest &lt; Test::Unit::TestCase
  def setup
    DataMapper.setup(:null, &quot;abstract::&quot;)
    DataMapper::Repository.context.push(DataMapper.repository(:null))
  end

  def teardown
    DataMapper::Repository.context.pop
  end

  def test_bar
    # ...
  end
end
</pre>



<p>There&#8217;s one kind of test that NullDB enables which the code we&#8217;ve looked at so far does not allow. That is, testing of after-save hooks. We can&#8217;t test an after-save hook with the code above, because a call to <code>#save</code> will error out before it ever gets to the after-save callback.</p>

<p>While DataMapper does not include an actual null-object style backend which turns all database operations into no-ops, it includes something close which will permit us to test after-save hooks. DataMapper ships with an in-memory store, which implements the DataMapper <span class="caps">API </span>in terms of a simple in-memory collection of Ruby objects. Here&#8217;s an example of triggering an after-save hook with an in-memory backend:</p>

</pre>

<pre name="code" class="ruby">
class Foo
  include DataMapper::Resource

  property :id, Serial

  after :save do
    puts &quot;Saved!&quot;
  end
end

DataMapper.setup(:ephemeral, &quot;in_memory::&quot;)

DataMapper.repository(:ephemeral) do
  f = Foo.new
  f.save
end
</pre>



<p>Running this script produces the output <tt>Saved!</tt>. This code also demonstrates the block-form of the the <code>DataMapper.repository</code> method, which pushes a session onto the repository stack, yields to the passed block, and then pops the session back off the stack.</p>

<p>So there you have it, a couple of quick and easy ways to approximate a null-database in DataMapper. I think it's a testament to DataMapper's design that it's so easy to assemble the pieces it provides in ways that the writers may not have anticipated. I hope you find these techniques useful!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=WCvvnKTp6o4:Cs4IYk_LY6U:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=WCvvnKTp6o4:Cs4IYk_LY6U:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=WCvvnKTp6o4:Cs4IYk_LY6U:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=WCvvnKTp6o4:Cs4IYk_LY6U:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=WCvvnKTp6o4:Cs4IYk_LY6U:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=WCvvnKTp6o4:Cs4IYk_LY6U:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/WCvvnKTp6o4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/27/nulldb-for-datamapper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/27/nulldb-for-datamapper/</feedburner:origLink></item>
		<item>
		<title>ISO8601 Dates in Ruby</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/MX8g1wDDiO8/</link>
		<comments>http://avdi.org/devblog/2009/10/25/iso8601-dates-in-ruby/#comments</comments>
		<pubDate>Mon, 26 Oct 2009 04:53:29 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[iso8601]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[simpledb]]></category>
		<category><![CDATA[time]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=269</guid>
		<description><![CDATA[ISO8601 is a standard for representing date/time information as a string. ISO8601 dates look like this: 2009-10-26T04:47:09Z.

There are a lot of good reasons to store dates in the ISO8601 format. The format is&#8230;

	Unambiguous. There is never any question how to interpret them.
	Human-readable. You can look at dates stored in ISO8601 and interpret them easily.
	Widely-supported. All [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/ISO_8601"><span class="caps">ISO8601</span></a> is a standard for representing date/time information as a string. <span class="caps">ISO8601 </span>dates look like this: <code>2009-10-26T04:47:09Z</code>.</p>

<a href="http://japhr.blogspot.com/2009/01/iso-8601-is-only-date-format.html">There are a lot of good reasons to store dates in the <span class="caps">ISO8601 </span>format</a>. The format is&#8230;<br />
<ul>
	<li>Unambiguous. There is never any question how to interpret them.</li>
	<li>Human-readable. You can look at dates stored in <span class="caps">ISO8601 </span>and interpret them easily.</li>
	<li>Widely-supported. All major programming languages have libraries for parsing and writing <span class="caps">ISO8601 </span>dates.</li>
	<li>Sortable. If you follow a few simple rules, <span class="caps">ISO8601 </span>dates sort lexicographically into the order you would expect.</li>
</ul>

<p>That last property makes <span class="caps">ISO8601 </span>a particularly good candidate for date/time storage in simple non-relational data stores like Amazon&#8217;s <a href="http://aws.amazon.com/simpledb/">SimpleDB</a>. Storing dates as <span class="caps">ISO8601 </span>lets you sort records by date in data stores which don&#8217;t support a native date/time data type &#8211; without sacrificing human-readability.</p>

<p>Using <span class="caps">ISO8601 </span>from Ruby couldn&#8217;t be simpler, if you know where to look for the tools. If you look at the Ruby <code>Time</code> class by itself, you won&#8217;t find any reference to <span class="caps">ISO8601.</span> The secret is to require the &#8216;time&#8217; library:</p>



<pre name="code" class="plain">
irb(main):001:0&gt; time = Time.now.utc.iso8601
NoMethodError: undefined method `iso8601' for Mon Oct 26 04:46:57 UTC 2009:Time
        from (irb):1
        from :0
irb(main):002:0&gt; require 'time'
=&gt; true
irb(main):003:0&gt; time = Time.now.utc.iso8601
=&gt; &quot;2009-10-26T04:47:09Z&quot;
irb(main):004:0&gt; Time.iso8601(time)
=&gt; Mon Oct 26 04:47:09 UTC 2009
</pre>



<p>Note the use of <code>utc</code> to convert the local time into universal time (aka Greenwich Mean).  This is important if you want your time strings to be lexicographically sortable. The &#8220;Z&#8221; on the end of the <span class="caps">ISO8601 </span>date indicates that it is in <span class="caps">UTC, </span>not a local time zone.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=MX8g1wDDiO8:Za4hdgDHj6Q:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=MX8g1wDDiO8:Za4hdgDHj6Q:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=MX8g1wDDiO8:Za4hdgDHj6Q:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=MX8g1wDDiO8:Za4hdgDHj6Q:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=MX8g1wDDiO8:Za4hdgDHj6Q:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=MX8g1wDDiO8:Za4hdgDHj6Q:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/MX8g1wDDiO8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/25/iso8601-dates-in-ruby/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/25/iso8601-dates-in-ruby/</feedburner:origLink></item>
		<item>
		<title>Double-Load Guards in Ruby</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/tTtn4-n__-A/</link>
		<comments>http://avdi.org/devblog/2009/10/22/double-load-guards-in-ruby/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 23:34:30 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[files]]></category>
		<category><![CDATA[load]]></category>
		<category><![CDATA[pathnames]]></category>
		<category><![CDATA[require]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=224</guid>
		<description><![CDATA[If you&#8217;ve ever worked with C or C++ you no doubt remember that one of continual headaches of working with those languages is avoiding double-inclusions of header files. Most C headers start and end with preprocessor directives in order to avoid this scenario:




#ifndef HELLO_H
#define HELLO_H

/* ... C code ... */

#endif




At first the situation in Ruby [...]]]></description>
			<content:encoded><![CDATA[<p>If you&#8217;ve ever worked with C or C++ you no doubt remember that one of continual headaches of working with those languages is avoiding double-inclusions of header files. Most C headers start and end with preprocessor directives in order to avoid this scenario:</p>



<pre name="code" class="c">
#ifndef HELLO_H
#define HELLO_H

/* ... C code ... */

#endif
</pre>



<p>At first the situation in Ruby seems much improved. We have <code>require</code>, after all, which ensures that a given file will only be loaded once. Or does it?</p>

<p>As it turns out all is not rosy in Ruby-land. Require works great for gems and system libraries. But when we start loading files relative to the current file, the old double-load problem rears it&#8217;s ugly head once more.</p>

<p>Let&#8217;s take a look at why this happens. First, we&#8217;ll define a file to load:</p>



<pre name="code" class="ruby">
# foo.rb
class Foo
  puts &quot;I'm being loaded!&quot;
end
</pre>



<p>Now we&#8217;ll define a client file which <code>require</code>s foo.rb:</p>



<pre name="code" class="ruby">
# client.rb
require File.join(File.dirname(__FILE__), './foo')
require File.join(File.dirname(__FILE__), '../lib/foo')
</pre>



<p>When we run the script above, we get the following output:<br />
<tt></p>

<pre>
I'm being loaded!
I'm being loaded!
</pre>

<p></tt></p>

<p>Of course, we&#8217;d never write a file like that, with the same library being required twice using two different paths. But in larger projects it is all too common for a file to be <code>require</code>d using a different path in different files. Because Ruby does not use canonicalized pathnames to check if it has already loaded a file, it assumes that the different paths must refer to different files and loads the file over and over again.</p>

<p>Is this a problem? Besides for slower application startup, the most common ill effect of repeated file loads is constant redefinition warnings. If you have a project that outputs a lot of warnings that look like this on startup&#8230;</p>

<p><tt></p>

<pre>
../lib/foo.rb:1: warning: already initialized constant FOO
</pre>

<p></tt></p>

<p>&#8230;you probably have some files being loaded twice or more times.</p>

<p>More serious and subtle side-effects of double-loading can occur though, especially if the files being reloaded do any class-level metaprogramming. Errors caused by double-loading can be strange and very difficult to track down.</p>

<p>So what do do? Well, first we need to find where the offending loads are originating from. In a large project this can be a daunting task.  Here&#8217;s some code I wrote to help track down double loads at <a href="http://devver.net">Devver</a>:</p>



<pre name="code" class="ruby">
ROOT_PATH = File.expand_path('..', File.dirname(__FILE__))

def require_with_reload_check(raw_path)

  unless $LOADED_FEATURES.include?(raw_path)
    $require_sites ||= {}
    site, line, info = caller.first.split(':')
    expanded_site = File.expand_path(site)
    load_dir = $LOAD_PATH.detect{|dir|
      File.exist?(File.expand_path(raw_path + &quot;.rb&quot;, dir))
    }
    expanded_path = File.expand_path(raw_path, load_dir)

    if (expanded_path.index(ROOT_PATH) == 0) &amp;&amp;
        $require_sites.key?(expanded_path) &amp;&amp;
        $require_sites[expanded_path][:as] != raw_path &amp;&amp;
        expanded_path !~ /test_helper$/
      warn &quot;!&quot; * 80
      warn &quot;#{expanded_path} is being reloaded!&quot;
      warn &quot;It was originally loaded as: #{$require_sites[expanded_path][:as]}&quot;
      warn &quot;From #{$require_sites[expanded_path][:in]}&quot;
      warn &quot;But now it is being loaded as: #{raw_path}&quot;
      warn &quot;In #{expanded_site}&quot;
      warn &quot;!&quot; * 80
    end

    $require_sites[expanded_path] = {
      :as =&gt; raw_path,
      :in =&gt; expanded_site
    }
  end
end

unless defined?($reload_guard_enabled)
  alias require_without_reload_check require
  alias require require_with_reload_check
  $reload_guard_enabled = true
end
</pre>



<p>This code should be loaded as early as possible in your project. Once loaded, it spits out some a very noisy warning every time a file is re-loaded using a different path:<br />
<tt></p>

<pre>
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/home/avdi/articles/double-load-guards/lib/foo is being reloaded!
It was originally loaded as: ././foo
From /home/avdi/articles/double-load-guards/lib/client.rb
But now it is being loaded as: ./../lib/foo
In /home/avdi/articles/double-load-guards/lib/client.rb
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
</pre>

<p></tt></p>

<p>But how do we avoid reloads, once we have located the offenders? The simplest remedy is to always expand relative paths before requiring them. I prefer to use the two-argument form of <code>File.expand()</code> to construct fully-qualified paths:</p>



<pre name="code" class="ruby">
# client.rb
require File.expand_path('../lib/foo', File.dirname(__FILE__))
</pre>



<p>Eliminate your double-loads, and your Ruby code will load faster, produce fewer warnings, and be that much less prone to bugs.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=tTtn4-n__-A:mZ2vKufER_w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=tTtn4-n__-A:mZ2vKufER_w:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=tTtn4-n__-A:mZ2vKufER_w:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=tTtn4-n__-A:mZ2vKufER_w:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=tTtn4-n__-A:mZ2vKufER_w:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=tTtn4-n__-A:mZ2vKufER_w:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/tTtn4-n__-A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/22/double-load-guards-in-ruby/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/22/double-load-guards-in-ruby/</feedburner:origLink></item>
		<item>
		<title>Patching flymake for Ruby development</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/zHgR7pqq208/</link>
		<comments>http://avdi.org/devblog/2009/10/21/patching-flymake-for-ruby-development/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 05:07:51 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[autotest]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[flymake]]></category>
		<category><![CDATA[merb]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=255</guid>
		<description><![CDATA[Flymake is a wonderful thing, and the Ruby/Flymake integration introduced by rails-mode is very, very handy. If you&#8217;re not familiar with it, Flymake is an Emacs minor mode that constantly checks your syntax in the background and marks up any code that has problems. It&#8217;s like inline spellcheck for your source code.

There&#8217;s a problem with [...]]]></description>
			<content:encoded><![CDATA[<p>Flymake is a wonderful thing, and the Ruby/Flymake integration introduced by rails-mode is very, very handy. If you&#8217;re not familiar with it, Flymake is an Emacs minor mode that constantly checks your syntax in the background and marks up any code that has problems. It&#8217;s like inline spellcheck for your source code.</p>

<p>There&#8217;s a problem with the Ruby integration, though, which is that the temporary files it generates frequently get mistaken for project files by tools like Autotest and Merb. I fixed this in my .emacs a long time ago, and after the second person asked about how I fixed it I thought I&#8217;d post my fix publicly.</p>

<p>Note: the following is a horrible kludge and the only nice thing I can say about it is that it works. In a perfect world Flymake would make it possible to customise the directory it uses instead of insisting on creating it&#8217;s files in the same directory as the originals. My version is monkeypatching in the first degree and if someone would take the time to clean it up and make an honest patch of it I&#8217;d happily use it.</p>

<script src="http://gist.github.com/215742.js"></script><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zHgR7pqq208:yxsYJFtKqbY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zHgR7pqq208:yxsYJFtKqbY:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=zHgR7pqq208:yxsYJFtKqbY:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zHgR7pqq208:yxsYJFtKqbY:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=zHgR7pqq208:yxsYJFtKqbY:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=zHgR7pqq208:yxsYJFtKqbY:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/zHgR7pqq208" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/21/patching-flymake-for-ruby-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/21/patching-flymake-for-ruby-development/</feedburner:origLink></item>
		<item>
		<title>Array-ifying Values</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/oWjchSc53fY/</link>
		<comments>http://avdi.org/devblog/2009/10/21/array-ifying-values/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 00:02:55 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[confidence]]></category>
		<category><![CDATA[idioms]]></category>
		<category><![CDATA[null]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=250</guid>
		<description><![CDATA[I can&#8217;t remember if I&#8217;ve written about this before. On the assumption that I haven&#8217;t, I&#8217;ll forge ahead.

As I&#8217;ve mentioned in the past I hate null checks. They clutter up code and add nothing meaningful to the code&#8217;s narrative. I hate checks to see if a value is singular or plural too. I guess what [...]]]></description>
			<content:encoded><![CDATA[<p>I can&#8217;t remember if I&#8217;ve written about this before. On the assumption that I haven&#8217;t, I&#8217;ll forge ahead.</p>

<p>As I&#8217;ve mentioned in the past I hate null checks. They clutter up code and add nothing meaningful to the code&#8217;s narrative. I hate checks to see if a value is singular or plural too. I guess what I&#8217;m saying is that I hate type checking and avoid it wherever possible.</p>

<p>Here&#8217;s a contrived example of some code that does both a null check and a cardinality check. It takes an argument and produces some <span class="caps">HTML </span>list item tags:</p>



<pre name="code" class="ruby">
def make_list(items)
  case items
  when Array then items.map{|item| html &quot;&lt;li&gt;#{item}&lt;/li&gt;&quot; }.join
  when nil then &quot;&quot;
  else &quot;&lt;li&gt;#{items}&lt;/li&gt;&quot; # singular value
  end
end
</pre>



<p>Blech. Thankfully there is an elegant idiom which cleans this code up nicely:</p>



<pre name="code" class="ruby">
def make_list(items)
  Array(items).map{|item| &quot;&lt;li&gt;#{item}&lt;/li&gt;&quot; }.join
end
</pre>



<p><a href="http://www.ruby-doc.org/core/classes/Kernel.html#M005967"><code>Kernel.Array()</code></a> is the &#8220;Array-ifier&#8221; method. It takes a value and always returns an array. And it&#8217;s pretty smart about how it translates:</p>



<pre name="code" class="ruby">
Array(&quot;foo&quot;) # =&gt; [&quot;foo&quot;]
Array(nil) # =&gt; []
Array([1,2,3]) # =&gt; [1,2,3]
Array(4..6) # =&gt; [4,5,6]
Array({:a =&gt; 1, :b =&gt; 2}) # =&gt; [[:b, 2], [:a, 1]]
</pre>



<p>As you can see, whatever you give it, you always get an Array back. Note in particular that if it is passed an Array, it returns the argument unaltered rather than wrapping it in another layer of array.</p>

<p>Under the covers, <code>Array()</code> tries to call <code>#to_ary</code> on the passed object, and if that fails it tries <code>#to_a</code>.</p>

<p>If you&#8217;ve been using Ruby for a while you might object &#8220;but isn&#8217;t that what <code>#to_a</code> is for?&#8221;. The problem with <code>#to_a</code> is that it&#8217;s old default behavior, which was to wrap a non-Array object in an Array, is deprecated. <code>Array()</code> is the future-proof way to array-ify arbitrary objects.</p>

<p>Now go forth, and <a href="http://avdi.org/devblog/2008/10/30/self-confident-code/comment-page-1/">write self-confident code</a>!</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=oWjchSc53fY:Iv0T6J7KyNo:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=oWjchSc53fY:Iv0T6J7KyNo:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=oWjchSc53fY:Iv0T6J7KyNo:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=oWjchSc53fY:Iv0T6J7KyNo:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=oWjchSc53fY:Iv0T6J7KyNo:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=oWjchSc53fY:Iv0T6J7KyNo:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/oWjchSc53fY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/21/array-ifying-values/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/21/array-ifying-values/</feedburner:origLink></item>
		<item>
		<title>Viewing REST service responses in a browser</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/9h34jna4BfU/</link>
		<comments>http://avdi.org/devblog/2009/10/20/viewing-rest-service-responses-in-a-browser/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 23:46:57 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=244</guid>
		<description><![CDATA[Have you ever had this experience? You&#8217;re debugging some RESTful service and trying to figure out why it&#8217;s returning 500s. So you dump the response body to STDOUT and HOLY HAND GRENADE THAT&#8217;S A LOT OF HTML!!!  Wouldn&#8217;t it be nice if you could just look at it in a browser?

Here ya go:




require 'tempfile'

def [...]]]></description>
			<content:encoded><![CDATA[<p>Have you ever had this experience? You&#8217;re debugging some <span class="caps">REST</span>ful service and trying to figure out why it&#8217;s returning 500s. So you dump the response body to <span class="caps">STDOUT </span>and <strong><span class="caps">HOLY HAND GRENADE THAT&#8217;S</span> A <span class="caps">LOT</span> OF <span class="caps">HTML</span>!!!</strong>  Wouldn&#8217;t it be nice if you could just look at it in a browser?</p>

<p>Here ya go:</p>



<pre name="code" class="ruby">
require 'tempfile'

def browse_string(body)
  Tempfile.open('browse_string') do |f|
    browser = ENV.fetch('BROWSER') { 'firefox' }
    f.write(body)
    f.close
    puts &quot;Starting browser #{browser} with response...&quot;
    unless system(browser, f.path)
      warn &quot;Error starting browser #{browser}&quot;
    end
  end
end
</pre>



<p>Just drop that in your debug script, in your .irbrc, or make a <a href="http://tagaholic.me/boson/">Boson</a> command out of it.  Then call it with the <span class="caps">HTML </span>you want to view:</p>



<pre name="code" class="ruby">
browse_string(response.body)
</pre>



<p>It even respects the <a href="http://catb.org/~esr/BROWSER/"><span class="caps">BROWSER</span></a> environment convention (well, sort of).</p>

<p>I&#8217;ve <a href="http://gist.github.com/214722">put the code on Gist</a> as well.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=9h34jna4BfU:C5Uls6wDz4k:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=9h34jna4BfU:C5Uls6wDz4k:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=9h34jna4BfU:C5Uls6wDz4k:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=9h34jna4BfU:C5Uls6wDz4k:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=9h34jna4BfU:C5Uls6wDz4k:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=9h34jna4BfU:C5Uls6wDz4k:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/9h34jna4BfU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/20/viewing-rest-service-responses-in-a-browser/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/20/viewing-rest-service-responses-in-a-browser/</feedburner:origLink></item>
		<item>
		<title>Safely executing commands with user data</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/GIYwP0yVpI0/</link>
		<comments>http://avdi.org/devblog/2009/10/19/safely-executing-commands/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 04:14:44 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[processes]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[security]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=236</guid>
		<description><![CDATA[Do you ever need to call out to a shell command with some user-supplied arguments?




category = 'riddles'
fortune = `fortune #{category}`






Q:      What's the difference between a Mac and an Etch-a-Sketch?
A:      You don't have to shake the Mac to clear the screen.




It all seems fine and good [...]]]></description>
			<content:encoded><![CDATA[<p>Do you ever need to call out to a shell command with some user-supplied arguments?</p>



<pre name="code" class="ruby">
category = 'riddles'
fortune = `fortune #{category}`
</pre>


<p><tt></p>

<pre>
Q:      What's the difference between a Mac and an Etch-a-Sketch?
A:      You don't have to shake the Mac to clear the screen.
</pre>

<p></tt></p>

<p>It all seems fine and good until some wise-ass comes along and messes things up for everyone.</p>



<pre name="code" class="ruby">
category = '; rm -rf *'
fortune = `fortune #{category}`
</pre>



<p>It doesn&#8217;t have to be this way though.  You can force process arguments to be interpreted strictly as strings instead of being subject to shell evaluation. You just have to use the multi-argument form of methods which start subprocesses.  This means that backquotes are out. We can use <code>#system()</code> though&#8230;</p>



<pre name="code" class="ruby">
filename = '; rm -rf *'
system('test', '-e', filename) # =&gt; false
</pre>



<p>That doesn&#8217;t help us with our original example, though.  We need the output.  <a href="http://www.ruby-doc.org/stdlib/libdoc/open3/rdoc/index.html">Open3</a> will do the trick:</p>



<pre name="code" class="ruby">
require 'open3'
category = '; rm -rf *'
output = &quot;&quot;
fortune = Open3.popen3('fortune', category) do |stdin, stdout, stderr|
  output += stdout.read
  output += stderr.read
end
puts output
</pre>


<p><tt></p>

<pre>
No fortunes found
</pre>

<p></tt></p>

<p>This technique is not a sure-fire defence against malicious data.  It will be of little help if the command you are invoking can start a subshell, so be especially careful when calling out to shells or to other scripting language interpreters.  But for simple commands it can provide a layer of protection.</p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=GIYwP0yVpI0:kbGwnVRJkaI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=GIYwP0yVpI0:kbGwnVRJkaI:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=GIYwP0yVpI0:kbGwnVRJkaI:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=GIYwP0yVpI0:kbGwnVRJkaI:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=GIYwP0yVpI0:kbGwnVRJkaI:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=GIYwP0yVpI0:kbGwnVRJkaI:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/GIYwP0yVpI0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/19/safely-executing-commands/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/19/safely-executing-commands/</feedburner:origLink></item>
		<item>
		<title>My WebOS Makefile</title>
		<link>http://feedproxy.google.com/~r/VirtuousCode/~3/eEMW4dBcBDM/</link>
		<comments>http://avdi.org/devblog/2009/10/17/my-webos-makefile/#comments</comments>
		<pubDate>Sat, 17 Oct 2009 20:53:26 +0000</pubDate>
		<dc:creator>avdi</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[gnu]]></category>
		<category><![CDATA[make]]></category>
		<category><![CDATA[makefle]]></category>
		<category><![CDATA[mojo]]></category>
		<category><![CDATA[palm]]></category>
		<category><![CDATA[pre]]></category>
		<category><![CDATA[webos]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=230</guid>
		<description><![CDATA[One of the first things I do when developing with a new framework is automate as much as I can.  When it comes to automating builds, GNU Make is still king of the hill.  Sure, it has a notoriously finicky syntax. But when you know what you&#8217;re doing no other tool can express [...]]]></description>
			<content:encoded><![CDATA[<p>One of the first things I do when developing with a new framework is automate as much as I can.  When it comes to automating builds, <a href="http://www.gnu.org/software/make/"><span class="caps">GNU</span> Make</a> is still king of the hill.  Sure, it has a notoriously finicky syntax. But when you know what you&#8217;re doing no other tool can express dependency information as concisely as Make.</p>

<p>I thought I&#8217;d post the Makefile I&#8217;ve been creating as I work on my first WebOS app.  It&#8217;s definitely a work in progress, but it&#8217;s capable of  building packages, launching the emulator, launching novacomd as a background job, and reloading the app. I&#8217;ve tried to get the dependencies right so that altering any part of the app forces a package rebuild before installing.</p>

<p>Note, this makefile is for Webos <span class="caps">SDK</span> 1.2 on an Ubuntu system.  It will probably require some small modifications to work on an OS X system.</p>

<p>The Makefile, along with a small helper script for launching novacomd, can be found at <a href="http://gist.github.com/212448">http://gist.github.com/212448</a>.  Please let me know if you find it useful!</p>

<p><span class="caps">EDIT</span>: I realised there&#8217;s one part of the Makefile which might not be immediately clear. In order to keep things <span class="caps">DRY,</span> I have the Makefile be the sole source of the app version (in the <code>VERSION</code> variable). Then I generate the appinfo.json file from a template (appinfo.json.m4) using the <a href="http://www.gnu.org/software/m4/"><span class="caps">GNU</span> M4 macro processor</a> and passing in the app version.</p>

<script src="http://gist.github.com/212448.js"></script><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=eEMW4dBcBDM:XpXGbxx3rnw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=eEMW4dBcBDM:XpXGbxx3rnw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=eEMW4dBcBDM:XpXGbxx3rnw:D7DqB2pKExk" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=eEMW4dBcBDM:XpXGbxx3rnw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?i=eEMW4dBcBDM:XpXGbxx3rnw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/VirtuousCode?a=eEMW4dBcBDM:XpXGbxx3rnw:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/VirtuousCode?d=cGdyc7Q-1BI" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/VirtuousCode/~4/eEMW4dBcBDM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://avdi.org/devblog/2009/10/17/my-webos-makefile/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc-sa/3.0/us/</creativeCommons:license>
	<feedburner:origLink>http://avdi.org/devblog/2009/10/17/my-webos-makefile/</feedburner:origLink></item>
	</channel>
</rss>
