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

<channel>
	<title>Techbelly &#187; ruby</title>
	<atom:link href="http://www.techbelly.com/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.techbelly.com</link>
	<description>Ben Griffiths&#039; weblog</description>
	<lastBuildDate>Sun, 18 Dec 2011 16:33:42 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Timing out a unix command</title>
		<link>http://www.techbelly.com/2010/07/17/timing-out-a-unix-command/</link>
		<comments>http://www.techbelly.com/2010/07/17/timing-out-a-unix-command/#comments</comments>
		<pubDate>Sat, 17 Jul 2010 22:00:36 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.techbelly.com/?p=466</guid>
		<description><![CDATA[It&#8217;s a while since I wrote a techy article here. Let&#8217;s change that. Last week I was asked how to handle running a shell command from Ruby, with the added requirement that if the command took longer than a certain time it should time out. Running commands from ruby is easy, and you should watch [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s a while since I wrote a techy article here. Let&#8217;s change that.</p>
<p>Last week I was asked how to handle running a shell command from Ruby, with the added requirement that if the command took longer than a certain time it should time out.</p>
<p>Running commands from ruby is easy, and you should watch <a href="http://www.rubymanor.org/harder/videos/short_order_ruby/">the video of my Ruby Manor talk</a> for some of the gory details.</p>
<p>But, is there a simple way to time-out a shell script using ruby? Well, you could probably write some heady threaded code that does it. But don&#8217;t. This is what the shell is for.</p>
<p>The usual Unix caveat applies: in the seventies, under the influence of prog rock, speed and the Californian sun, a bearded fellow already wrote the exact tool you want. And that tool has no doubt shipped with every Unix ever since. And everyone but you uses it daily.</p>
<p> But, this time, I couldn&#8217;t find that tool. There must be one. Anyone know of it?</p>
<p>Anyway, this is what I did:</p>
<blockquote>
<pre>
#!/bin/bash

# timeout
# Usage: timeout timeout_in_seconds command [args]
# Example: timeout 120 wget http://www.slowserver.com 

timeout=$1
command=$2
command_args=${@:3} 

$command $command_args &#38;
pid=$!
( sleep $timeout &#38;&#38; kill -9 $pid ) &#38;&gt; /dev/null

wait $pid &#38;&gt; /dev/null
exitcode=$?
exit $exitcode
</pre>
</blockquote>
<p>We launch the main command in the background; then, we launch a second command that sleeps for the requested timeout before attempting to kill the first one; then, we wait for the first command to finish (either of its own accord or thanks to a kill signal), returning its exit code as our own.</p>
<p> It&#8217;s brutish and dumb, but for most cases this simple approach works.</p>
<p>Be careful if your machine is going through PIDs like billy-o -you could end up sending the <span class="caps">TERM</span> signal to the wrong process -, but in general use that shouldn&#8217;t be a problem.</p>
<p>You could make it safer by storing start time and <span class="caps">PID</span> and making sure they both match, or something similar. Left as an exercise to the reader, as us lazy folk say.</p>
<p>A few bash things you may not have seen before: the special parameters <strong>!</strong>, <strong>@</strong> and <strong>?</strong>, <strong>wait</strong> and bash parameter substring expansion. </p>
<p><strong>$!</strong> expands to the PID of the most recently executed background command, and <strong>$?</strong> expands to the exit status of the most recently executed foreground command. </p>
<p><strong>&#8220;$@&#8221;</strong> is equivalent to <strong>&#8220;$1&#8243; &#8220;$2&#8243;</strong>&#8230;  I use the <strong>${parameter:offset}</strong> notation to grab a slice that array. </p>
<p><strong>wait</strong> is a useful shell built-in that takes any PID, waits for it to finish and returns its exit code.</p>
<p>Much more detail, of course, lurks in the bash man page &#8211; I still find I  look up these cryptic characters or copy them from an existing script.</p>
<p>There&#8217;s a standard tool that does this better, right?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techbelly.com/2010/07/17/timing-out-a-unix-command/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Sucking tweets into a local database</title>
		<link>http://www.techbelly.com/2009/11/14/sucking-tweets-into-a-local-database/</link>
		<comments>http://www.techbelly.com/2009/11/14/sucking-tweets-into-a-local-database/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 01:47:27 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.techbelly.com/?p=406</guid>
		<description><![CDATA[A friend asked me yesterday if I could snap together a script to build a local database of tweets using the twitter search API. This is what I came up with. The script takes one argument &#8211; the term to search on &#8211; and creates a sqlite3 database in the current directory containing all the [...]]]></description>
			<content:encoded><![CDATA[<p>A friend asked me yesterday if I could snap together a script to build a local database of tweets using the twitter search API.</p>
<p><a href="http://pastie.textmate.org/698244">This is what I came up with.</a> </p>
<p>The script takes one argument &#8211; the term to search on &#8211; and creates a sqlite3 database in the current directory containing all the tweets that the twitter search API returns for that term. </p>
<p>It requires <a href="http://datamapper.org/">datamapper</a> and <a href="http://github.com/dancroak/twitter-search">twitter_search</a> gems to be installed. </p>
<p>Have at it, make it better, bend it to your twitter-slurping needs.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techbelly.com/2009/11/14/sucking-tweets-into-a-local-database/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Play IF in Campfire</title>
		<link>http://www.techbelly.com/2009/11/13/play-if-in-campfire/</link>
		<comments>http://www.techbelly.com/2009/11/13/play-if-in-campfire/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 23:56:08 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[campfire]]></category>
		<category><![CDATA[if]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.techbelly.com/?p=398</guid>
		<description><![CDATA[Ruby is an excellent language for writing small scripts to glue stuff together. Here&#8217;s a script I knocked together that lets you play a zcode text adventure (interactive fiction) with your friends in Campfire. You&#8217;ll need a room, account, etc. in Campfire; you&#8217;ll need to compile this version of dumb-frotz; and you&#8217;ll need a zcode [...]]]></description>
			<content:encoded><![CDATA[<p>Ruby is an excellent language for writing small scripts to glue stuff together. Here&#8217;s <a href="http://techbelly.com/campfrotz.rb">a script</a> I knocked together that lets you play a <a href="http://en.wikipedia.org/wiki/Z-machine">zcode</a> text adventure (interactive fiction) with your friends in <a href="http://campfirenow.com/">Campfire</a>.</p>
<p>You&#8217;ll need a room, account, etc. in Campfire; you&#8217;ll need to compile this <a href="http://woz.gs/tim/zork/">version of dumb-frotz</a>; and you&#8217;ll need a zcode file to play &#8211; plenty of those at the <a href="http://ifdb.tads.org">Interactive Fiction Database</a>. </p>
<p>I only wrote about this because <a href="http://twitter.com/lazyatom/status/5682190846">@lazyatom called me a genius</a> for doing it. Which was nice.</p>
<p><a href="http://techbelly.com/campfrotz.rb">Have fun.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.techbelly.com/2009/11/13/play-if-in-campfire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby on Rails popularity</title>
		<link>http://www.techbelly.com/2006/05/11/ruby-on-rails-popularity/</link>
		<comments>http://www.techbelly.com/2006/05/11/ruby-on-rails-popularity/#comments</comments>
		<pubDate>Thu, 11 May 2006 10:28:33 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[martin fowler]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[rubyonrails]]></category>

		<guid isPermaLink="false">http://www.techbelly.com/?p=286</guid>
		<description><![CDATA[Even seasoned IT professionals occasionally give blank stares when I tell them that we program in ruby, using ruby on rails. What with a recent endorsement from Martin Fowler and this graph &#8211; spotted on Jason Huggins&#8217; blog &#8211; it seems that ruby and rails are truly gaining the popularity they deserve.]]></description>
			<content:encoded><![CDATA[<p>Even seasoned IT professionals occasionally give blank stares when I tell them that we program in <a href="http://ruby-lang.org" title="">ruby</a>, using <a href="http://www.rubyonrails.org" title="">ruby on rails</a>.</p>
<p>What with a <a href="http://martinfowler.com/bliki/EvaluatingRuby.html" title="">recent endorsement</a> from Martin Fowler and <a href="http://www.google.com/trends?q=python+programming%2C+ruby+on+rails&#38;ctab=0&#38;date=all&#38;geo=all" title="">this graph</a>  &#8211; spotted on <a href="http://www.jrandolph.com/blog/?p=30" title="">Jason Huggins&#8217; blog</a> &#8211; it seems that ruby and rails are truly gaining the popularity they deserve.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techbelly.com/2006/05/11/ruby-on-rails-popularity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mock objects and life expectancy</title>
		<link>http://www.techbelly.com/2005/06/26/mock-objects-and-life-expectancy/</link>
		<comments>http://www.techbelly.com/2005/06/26/mock-objects-and-life-expectancy/#comments</comments>
		<pubDate>Sun, 26 Jun 2005 08:59:24 +0000</pubDate>
		<dc:creator>Ben</dc:creator>
				<category><![CDATA[Internet]]></category>
		<category><![CDATA[mockobjects]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.techbelly.com/?p=228</guid>
		<description><![CDATA[For my sins, I&#8217;m a smoker and caffeine-addict. On a previous project, before I discovered the mock-objects religion, it took so long to run unit tests before a code check-in that I had time to nip downstairs, get a coffee, have a quick cigarette and be back upstairs before the green bar was halfway done. [...]]]></description>
			<content:encoded><![CDATA[<p>For my sins, I&#8217;m a smoker and caffeine-addict. On a previous project, before I discovered the <a href="http://www.mockobjects.com" title="">mock-objects</a> religion, it took so long to run unit tests before a code check-in that I had time to nip downstairs, get a coffee, have a quick cigarette and be back upstairs before the <a href="http://tap.testautomationpatterns.com:8080/green%20bar.html" title="">green bar</a> was halfway done. I knew things were bad when I realised I was on 20+ check-ins per day.</p>
<p>I think that the biggest advantage of using mock objects is that your tests run quicker. I find that the quicker I can run all the tests, the braver I become in fixing any <a href="http://www.37signals.com/svn/archives/000916.php" title="">broken windows</a> that have crept into the code. But there are other significant advantages too: design decisions can be defered until you have more knowlege about the domain; classes tend to end up less tightly coupled; girls throw themselves at you in the street. Well, perhaps two of those three things are true.</p>
<p>An example from our codebase using the <a href="http://rubyforge.org/projects/schmock/" title="">Schmock</a> mock objects library that we developed while writing our code here.</p>
<p>Although we&#8217;re programming in Rails, our controller layer and model layer are separated by some service objects &#8211; one of which handles our wiki implementation. To test the wiki controller, we mock out the actual wiki using a SchMock:</p>
<pre>
class WikiControllerTest &lt; Test::Unit::TestCase
</pre>
<p>In the <code>setup</code> method we create the mock_wiki and inject it into the application controller from which everything that uses it can access it.</p>
</pre>
<pre>
  def setup
    @mock_wiki = SchMock.new
    ApplicationController.wiki = @mock_wiki
    @controller = WikiController.new
    @request    = ActionController::TestRequest.new
    @response   = ActionController::TestResponse.new
end
</pre>
<p>At the end of every test we verify that the mock_wiki has had all its expectations fulfilled.</p>
<pre>
  def teardown
    @mock_wiki.__verify
  end
</pre>
<p>Now the real meat of the test. We want to make sure that if we try to edit a non-existing page that we&#8217;re redirected to the &#8216;new&#8217; action. We tell our mock_wiki to expect a call to page_exists? with a parameter &#8216;nonexistent&#8217; and when it gets it to return false.</p>
<p>I find this simpler than using the built-in fixtures functionality in rails to set up the database to a known state, because the fixture appears right there in the code rather than derived from two-step removed database tables and I don&#8217;t have to remember to delete any pre-existing state from the database. It also runs much, much quicker.</p>
<pre>
  def test_should_redirect_to_new_page_form_if_asked_to_edit_nonexisting_page
     @mock_wiki.__expects(:page_exists?).with('nonexistent').returns(false)
     get :edit, { :page =&gt; 'nonexistent'}
     assert_redirected_to :action =&gt; 'new', :page =&gt; 'nonexistent'
  end
end
</pre>
<p>I think my life-expectancy has been greatly improved through the use of mock-objects and I thank the good chaps who wrote and promoted the original mock-objects &#8211; people like <a href="http://stevef.truemesh.com/" title="">Steve Freeman</a>, <a href="http://nat.truemesh.com/" title="">Nat Price</a>, <a href="http://ivan.truemesh.com/" title="">Ivan Moore</a> and <a href="http://joe.truemesh.com/blog/" title="">Joe Walnes</a> &#8211; who write much more elegantly than me on the topic.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.techbelly.com/2005/06/26/mock-objects-and-life-expectancy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

