<?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>3hv</title>
	
	<link>http://www.3hv.co.uk/blog</link>
	<description>beautiful code for elegant web sites</description>
	<lastBuildDate>Tue, 27 Oct 2009 17:55:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</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/3hv" /><feedburner:info uri="3hv" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>3hv</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Making decisions at a startup</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/gDJi97M2jlM/</link>
		<comments>http://www.3hv.co.uk/blog/2009/10/27/making-decisions-at-a-startup/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 17:55:29 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Managing Successful Projects]]></category>
		<category><![CDATA[decisions]]></category>
		<category><![CDATA[flow charts]]></category>
		<category><![CDATA[startups]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=602</guid>
		<description><![CDATA[One of the problems of being at a startup is the overwhelming amount of work.  So much to do, so little time!
Luckily, this helpful flow-chart helps you decide what to do next.  
]]></description>
			<content:encoded><![CDATA[<p>One of the problems of being at a startup is the overwhelming amount of work.  So much to do, so little time!</p>
<p>Luckily, this helpful flow-chart helps you decide what to do next.  <img src="http://www.3hv.co.uk/blog/wp-content/uploads/2009/10/Startup-Decision-Maker-193x300.png" alt="Startup Decision Maker" title="Startup Decision Maker" width="193" height="300" class="alignright size-medium wp-image-603" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/10/27/making-decisions-at-a-startup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/10/27/making-decisions-at-a-startup/</feedburner:origLink></item>
		<item>
		<title>Play to your strengths</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/0tZI5aPNnW8/</link>
		<comments>http://www.3hv.co.uk/blog/2009/10/11/play-to-your-strengths/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 15:28:56 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[Managing Successful Projects]]></category>
		<category><![CDATA[corporate culture]]></category>
		<category><![CDATA[product positioning]]></category>
		<category><![CDATA[sales]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=593</guid>
		<description><![CDATA[I used to work for a company that built a complicated desktop application, let&#8217;s call it Roloduck.  The original version was written in about 1999-2000 and subsequent versions (including a total rewrite) were built over the first six years of the new millenium.  Over that time my job title varied between developer, senior [...]]]></description>
			<content:encoded><![CDATA[<p>I used to work for a company that built a complicated desktop application, let&#8217;s call it Roloduck.  The original version was written in about 1999-2000 and subsequent versions (including a total rewrite) were built over the first six years of the new millenium.  Over that time my job title varied between developer, senior developer, lead architect, project leader, team leader and technical director.  Amongst other things.  </p>
<p>One of the major trends in software development at that time (at least for desktop applications) was to offer options &#8211; make it configurable and you can please everyone.  And you can then sell &#8220;consultancy days&#8221; as it takes two weeks post-installation before the thing is usable, as you tick all the right boxes and choose all the right options.  It also means you can say &#8220;hmm, well, there are eight different ways to do that, each with different pros and cons&#8221; (as opposed to saying &#8220;we can do exactly what you want&#8221; or &#8220;no, sorry, we don&#8217;t do that&#8221;).  </p>
<p>So this was a big complicated software project; large enough that no one person knew it all the way through, with a variety of different architectures in-built (COM objects is how you do this stuff; oh no, now it&#8217;s COM+, now it&#8217;s ADO-disconnected and so on).  </p>
<p>But we were only a small company.  At its largest there were probably ten people working on the product at any one time.  However, if you read the company communications you could never tell &#8211; it was all the bland, marketing-droid, use three-hundred-words-when-one-would-do style.  Our email signatures had the sixteen paragraph disclaimer &#8211; &#8220;this is only intended for the intended recipient and if you are not its intended then wipe your memory immediately and burn your computer to prevent accidental ingestion&#8221;.  This worked so well, some of our customers were amazed when they found out how many people we actually had &#8211; they thought we were a multinational with hundreds of developers across thousands of countries.  </p>
<p>Over the years, we would consistently come across a single competitor &#8211; let&#8217;s call them Crump Builder.  We poached our sales director from them, so we had a pretty good idea of what they were capable of and how they worked.  We were small fry, they had funding and a team several times bigger than ours.  They had also been going longer than us, so they had an even bigger set of preferences, options and modules to choose from.  Most of the time, the sales process would come down to a choice between Roloduck and Crump Builder, and in the vast majority of cases, the prospect would choose Crump Builder.  </p>
<p>At the time, I thought this was because we were behind them.  They had the more polished, more finished product that did more and went further.  But, since the demise of Roloduck (the company went bust recently) I&#8217;ve had to revise that view.  You see, one of Roloduck&#8217;s old customers has chosen Crump Builder as the replacement for their now defunct Roloduck system.  And she said that Crump Builder simply does not do a lot of the stuff that they need, whereas Roloduck does.  </p>
<p>This news amazed me.  Why did we consistently lose out to Crump Builder in those countless sales pitches?  </p>
<p>Having thought about this, the only reason I can come up with is that we were not playing to our strengths.  We were chasing their tails all the time.  &#8220;We know they do X and we don&#8217;t yet; but we will soon&#8221;.  &#8220;Yes, their version is pretty slick and ours is a bit clunky&#8221;.  We were trying to present ourselves as their equals, equivalent in size and structure, in fact bigger than them in size and structure.  But, because we were smaller, we were being found out.  Not once, in our competitive analysis did we say &#8220;they are strong there, but we are strong here, so we should push this instead&#8221;. We should have pitched it as &#8220;we are the small guys &#8211; meaning you will get personalised service&#8221;, &#8220;our bit isn&#8217;t finished yet, so we can tailor it exactly to how you need it&#8221;</p>
<p>This is exactly what we have planned for our new venture.  There are only two of us, so you will have the focussed attention of at least 50% of the company.  We can&#8217;t afford lawyers or committees, so all the personality won&#8217;t be mangled out of our communications (bad jokes and all).  And as we&#8217;re only small we can&#8217;t afford any waste, in either resources or time.  So we will do what you need in the quickest, most efficient way possible.  It will not work for everyone, but it will work fantastically for some.  Those are <em>our</em> strengths and we <em>will</em> play to them.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/10/11/play-to-your-strengths/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/10/11/play-to-your-strengths/</feedburner:origLink></item>
		<item>
		<title>Posting gems to Rubyforge</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/QiIvyoSUv7Q/</link>
		<comments>http://www.3hv.co.uk/blog/2009/10/06/posting-gems-to-rubyforge/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 18:20:04 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby on Rails and Software Development]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=588</guid>
		<description><![CDATA[Github aren&#8217;t building new gems at the moment as they finalise their move to Rackspace.  So what do you do if you&#8217;ve got a gem that you would like to make available?  
Gemcutter&#8217;s the new kid on the block &#8211; it works as a set of plugins to the gem command that mean [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com">Github</a> aren&#8217;t building new gems at the moment as they finalise their move to Rackspace.  So what do you do if you&#8217;ve got a gem that you would like to make available?  </p>
<p><a href="http://gemcutter.org">Gemcutter&#8217;s</a> the new kid on the block &#8211; it works as a set of plugins to the gem command that mean you can simply go `gem push my.gem` and it becomes available to the world.  Nice as this is, gemcutter&#8217;s still pretty young and is currently hosted off <a href="http://www.mail-archive.com/rubygems-developers@rubyforge.org/msg03123.html">one guy&#8217;s S3 account</a>.  </p>
<p>So we went back to good old-fashioned <a href="http://rubyforge.org">Rubyforge</a>.  Except, believe it or not, I&#8217;d never published to Rubyforge before.  And it wasn&#8217;t as straightforward as it could have been.  </p>
<p>I was using the <a href="http://github.com/fauna/echoe">echoe</a> library to build my gem &#8211; which gave me a simple `rake manifest`, `rake release` workflow.  All good.  When you `rake release` it asks if you want to publish to rubyforge; you say &#8220;yes&#8221; and go to bed happy.  </p>
<p>Or not in my case.  </p>
<p>Firstly, you need to actually configure rubyforge.  Install the rubyforge gem, then use `rubyforge setup` to put in your username and password.  Then use `rubyforge config` to make them stick.  </p>
<p>That done, I `rake release`d.  And got a &#8220;no group_id configured for mygem&#8221; error.  Eh?  Googling seemed no help whatsoever &#8211; it was mentioned in a few places but people seemed to have resolved it without actually posting their solutions (or I was being blind).  </p>
<p>What you need to do is tell Rubyforge where to put your gem.  In our case we already had a project on Rubyforge that the gem could be attached to &#8211; so `rubyforge create_package project_name gem_name` did the trick.  Otherwise you need to get a project set up to house your gem.  </p>
<p>But it still didn&#8217;t work.  This time complaining about a processor id.  I had no idea what I was looking for this time, until I discovered this <a href="http://pastie.org/180892">pastie</a> by Dr Nic.  The autogenerated config file (normally in ~/.rubyforge/auto-config.yml) is missing some vital information &#8211; namely codes for different processor architectures.  I pasted the list into your config file and then tried the `rake release` again.  And this time it worked!</p>
<pre><code>
processor_ids:
  IA64: 6000
  AMD-64: 1500
  Any: 8000
  Sparc: 4000
  PPC: 2000
  Other: 9999
  Alpha: 7000
  i386: 1000
  UltraSparc: 5000
  MIPS: 3000
</code></pre>
<p>So for the sake of posterity &#8211; and anyone else who gets &#8220;no group_id configured for mygem&#8221; or &#8220;no processor_id configured for mygem&#8221; messages, I thought I should let you know how I got there.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/10/06/posting-gems-to-rubyforge/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/10/06/posting-gems-to-rubyforge/</feedburner:origLink></item>
		<item>
		<title>It happens to the best of us</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/mJYrnwZ-ddo/</link>
		<comments>http://www.3hv.co.uk/blog/2009/10/05/it-happens-to-the-best-of-us/#comments</comments>
		<pubDate>Mon, 05 Oct 2009 16:21:53 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[Ruby on Rails and Software Development]]></category>
		<category><![CDATA[Writing Reliable, Bug-Free Code]]></category>
		<category><![CDATA[Bug-Free Code]]></category>
		<category><![CDATA[bugs]]></category>
		<category><![CDATA[cucumber]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[Writing Reliable]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=581</guid>
		<description><![CDATA[We just had some customers report a bug. Not good. We didn&#8217;t get an exception email. All the tests passed. We couldn&#8217;t see anything untoward in the log files.  But it was there. We could reproduce it, both in staging and in production. Not good at all. 
But the weirdest thing was we couldn&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>We just had some customers report a bug. Not good. We didn&#8217;t get an exception email. All the tests passed. We couldn&#8217;t see anything untoward in the log files.  But it was there. We could reproduce it, both in staging and in production. Not good at all. </p>
<p>But the weirdest thing was we couldn&#8217;t figure out the cause. Well I could see why the code was failing (after adding some extra log messages). But &#8216;git blame&#8217; said those lines of code were unchanged in twelve months.  Why hadn&#8217;t people complained before?  Why hadn&#8217;t we <em>noticed</em> it?</p>
<p>After much hunting through log files we found the point when the feature last worked. It coincided with a deployment. That deployment was our Rails 2.3.4 forms vulnerability fix. And the bug was in a form &#8211; a missing form parameter that earlier versions of Rails ignored, the newer Rails was choking on.  </p>
<p>But why didn&#8217;t the tests catch it?  </p>
<p>After more hunting I saw that the Cucumber test that exercised the form didn&#8217;t have a &#8220;When I press the Update button&#8221; step.  And the subsequent tests were passing, even though the update button hadn&#8217;t been pressed.  </p>
<p>So I added the step in and made the feature pass.  Then deployed it as an emergency fix.  </p>
<p>However, what are the lessons to learn here (as there are always some)? </p>
<ul>
<li>Firstly, testing cannot catch everything.  </li>
<li>Secondly, the cracks in your tests are where the bugs are.  </li>
<li>Thirdly, we probably need some sort of peer review for tests.  I feel that this is more important than for code, because once the tests are right you can refactor the code without worry.  </li>
<li>Fourthly, you really need to <strong>log everything</strong>.  Absolutely everything.  Don&#8217;t worry about your huge log files &#8211; that&#8217;s what `logrotate` is for.  Get it written down so that one time when you have an obscure bug, you&#8217;ll be able to find it easily.  </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/10/05/it-happens-to-the-best-of-us/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/10/05/it-happens-to-the-best-of-us/</feedburner:origLink></item>
		<item>
		<title>ThinkVisibility: the things that get left behind in the web development process</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/PmiZUw1FwHk/</link>
		<comments>http://www.3hv.co.uk/blog/2009/09/13/thinkvisibility-the-things-that-get-left-behind-in-the-web-development-process/#comments</comments>
		<pubDate>Sun, 13 Sep 2009 20:24:17 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[al carlton]]></category>
		<category><![CDATA[artur ortega]]></category>
		<category><![CDATA[chris clarkson]]></category>
		<category><![CDATA[dominic hodgson]]></category>
		<category><![CDATA[joost de valk]]></category>
		<category><![CDATA[judith lewis]]></category>
		<category><![CDATA[julian sambles]]></category>
		<category><![CDATA[kieron donoghue]]></category>
		<category><![CDATA[paul robinson]]></category>
		<category><![CDATA[thinkvisibility]]></category>
		<category><![CDATA[zoe piper]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=573</guid>
		<description><![CDATA[I&#8217;ll admit it &#8211; I&#8217;m biased.  Dom&#8217;s a friend of mine and we do an occasional podcast together (which, incidentally, I will be speaking about at Geekup Leeds this coming Wednesday).  So even if ThinkVisibility was shit I would have said it was good.  
But it wasn&#8217;t shit.  It wasn&#8217;t good. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ll admit it &#8211; I&#8217;m biased.  <a href="http://www.thehodge.co.uk/">Dom</a>&#8217;s a friend of mine and we do an occasional <a href="http://www.techietubbies.co.uk/">podcast</a> together (which, incidentally, I will be speaking about at <a href="http://upcoming.yahoo.com/event/4414833">Geekup Leeds</a> this coming Wednesday).  So even if <a href="http://www.thinkvisibility.com/">ThinkVisibility</a> was shit I would have said it was good.  </p>
<p>But it wasn&#8217;t shit.  It wasn&#8217;t good.  It was absolutely great.  </p>
<p>Things started on the Friday with a free seminar by <a href="http://www.timnash.co.uk/">Tim Nash</a> &#8211; all about user profiling.  I missed the first half hour (as my bus had to stop and give another bus a jump start &#8211; it&#8217;s <a href="http://twitter.com/xbaz/status/3909560482">true</a>, honest), so was a bit befuddled as we had to decide on keywords for the other attendees (based upon the introductions they had given whilst I was on the other side of town).  But I came away from the session with a list of improvements to make to one of my <a href="http://www.eighteensixtyfive.co.uk/">blogs</a> so it wasn&#8217;t a wasted trip.  </p>
<p>This was swiftly followed by several pints of Leeds Brewery Pale Ale on an empty stomach, resulting in me failing to buy <a href="http://www.conferencecalendar.com/">Al Carlton</a> a drink, but being bought one by <a href="http://www.chrisg.com/">Chris Garrett</a> (thank you).  I sloped off home before I could get caught up in one of Al&#8217;s <a href="http://twitter.com/AlCarlton/status/3925921119">legendary nights out</a>.  </p>
<p>On to Saturday and the conference proper.  Despite living in Leeds for years, I&#8217;d never really been to Clarence Dock, home to the Alea Casino.  I was actually quite impressed &#8211; in a &#8220;let&#8217;s try and look like London&#8221; kind of way.  Slide into the venue just before ten, pick up my lanyard and creep into the introductory session.  </p>
<p><a href="http://yoast.com/">Joost de Valk</a> told us all about optimising Wordpress.  Speed is key &#8211; cache (using Memcached if possible) and distribute your assets using a <a href="http://www.brightbox.co.uk/services/brightbox-cdn">Content Delivery Network</a> to reduce those page load times.  </p>
<p>Next, Julian Sambles told us about how the <a href="http://www.telegraph.co.uk/">Telegraph</a> changed its entire culture to adapt to the digital world.  It&#8217;s certainly a success story (look at the number of times <a href="http://daringfireball.net">Gruber</a> links to Telegraph stories; a couple of years ago if he wanted a UK angle it would have been the Guardian) &#8211; and Julian emphasised that it was mainly a cultural change, not a technical one.  Another interesting fact &#8211; their digital division not only generates revenue but actually makes a profit (unlike, if you believe the rumours, the print division).  </p>
<p>And on to my highlight.  I had the pleasure of meeting <a href="http://www.deCabbit.com/">Judith Lewis</a> in the pub the night before and she was absolutely charming.  But her talk was even better.  She told us about how Google&#8217;s embedding search results for other media types within the standard search results page has changed the game (images, videos and news results pushing other, textual results, further down the list and often off the first page completely).  Meaning you should work at getting into the video results, the image results and the news results.  But the best bits were when she stepped away from the mic and told us about the &#8220;dark arts&#8221; of search.  Which, of course, I could never repeat here.  She then ended her talk with a lolcat.  </p>
<p>Leading us to the lunchtime panel.  There were a few complaints about the food.  Personally I wasn&#8217;t bothered.  I was very hungry, grabbed a few ropey sandwiches and had a couple of lovely cookies.  No complaints from me; especially for less than £100.  But, by the sounds of it, some people missed out because of the queues, which would be annoying.  While we were eating, there was the lunchtime panel &#8211; Al Carlton, Chris Garrett, <a href="http://www.here.org.uk/">Kieron Donoghue</a> and <del datetime="2009-09-13T19:50:36+00:00">Patrick Altoft</del> Dominic Hodgson taking questions via Twitter.  There was also a side-competition &#8211; how many times will Kieron mention <a href="http://www.sharemyplaylists.com/">Share My Playlists</a>?  Of course, yours truly got a big laugh and round of applause for <a href="http://twitter.com/xbaz/status/3932851552">my question</a>.  </p>
<p>On to the afternoon sessions &#8211; where the venue was split into three.  First up was <a href="http://www.vagueware.com/">Paul Robinson</a>, who I vaguely knew from Geekups and my day job.  He was explaining how the likes of Amazon and Last.fm&#8217;s recommendation engines work &#8211; and how by matching similarities between different user data and behaviour, you can add intelligence to your site.  Interesting stuff.  </p>
<p>Next up was <a href="http://www.sunshine.co.uk/">Chris Clarkson</a> telling us the story behind Holiday Watchdog &#8211; an affiliate site he and a friend founded in 2003 and sold in 2007.  The main thing to take away from his talk was that being a limited company may protect you from company liabilities &#8211; but it doesn&#8217;t save you from being sued for defamation.  </p>
<p>Then was <a href="http://www.piggynap.com/">Zoe Piper</a> talking about Google Adwords.  There was a lot of interesting stuff here, but unfortunately, I didn&#8217;t hear parts of it.  Because the main room had been split into three, the speakers could not use the microphones &#8211; and Zoe had a quiet voice, meaning I missed big chunks of her talk.  This is my only complaint of the day &#8211; it&#8217;s not Zoe&#8217;s fault &#8211; just an artefact of the room arrangement.  </p>
<p>And finally <a href="http://twitter.com/DesignedByBlind">Artur Ortega</a> gave a talk on how disabilities have fueled innovation in the technology industry.  Basically every piece of technology, that we take for granted, in our offices has a history of helping overcome disabilities; from keyboards to scanners (and mostly designed by Bell Labs, as Alexander Graham Bell&#8217;s wife was deaf and so he was motivated to solve the problems that triggered).  </p>
<p>As I said up-front, this was a great day and a half.  I learnt a lot, got to meet some great people and am once again reminded how much there is in the &#8220;web industry&#8221; that I know nothing about.  It has certainly changed the way I approach my next venture.  </p>
<p>The next Think Visibility will be in March.  You better make sure that you attend.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/09/13/thinkvisibility-the-things-that-get-left-behind-in-the-web-development-process/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/09/13/thinkvisibility-the-things-that-get-left-behind-in-the-web-development-process/</feedburner:origLink></item>
		<item>
		<title>Why the lucky stiff</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/sfWAm3bAelU/</link>
		<comments>http://www.3hv.co.uk/blog/2009/08/21/why-the-lucky-stiff/#comments</comments>
		<pubDate>Fri, 21 Aug 2009 08:54:48 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[why the lucky stiff]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=565</guid>
		<description><![CDATA[So _why has vanished off the internet.  
I have no idea who he is or why he&#8217;s gone.  But _why meant a lot to Ruby developers, myself included.  He represented style and grace and art and weirdness &#8211; that Ruby was about more than just getting the job done in the most [...]]]></description>
			<content:encoded><![CDATA[<p>So _why has <a href="http://www.rubyinside.com/why-the-lucky-stiff-is-missing-2278.html">vanished</a> off the internet.  </p>
<p>I have no idea who he is or why he&#8217;s gone.  But _why meant a lot to Ruby developers, myself included.  He represented style and grace and art and weirdness &#8211; that Ruby was about more than just getting the job done in the most efficient way possible.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/08/21/why-the-lucky-stiff/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/08/21/why-the-lucky-stiff/</feedburner:origLink></item>
		<item>
		<title>Constructors in Ruby are not guaranteed to be called</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/s2ayhwfK3XQ/</link>
		<comments>http://www.3hv.co.uk/blog/2009/06/03/constructors-in-ruby-are-not-guaranteed-to-be-called/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 21:28:58 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby on Rails and Software Development]]></category>
		<category><![CDATA[constructors]]></category>
		<category><![CDATA[language]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=557</guid>
		<description><![CDATA[Today, Caius made a discovery that shocked me.  
He had a class, descending from ActiveRecord::Base, with a custom constructor (initialize method).  To debug it, he had the constructor raise an exception.  In the console, Thingy.new(params) raised the exception as expected.  But wotsit.thingies.find_by_field(value) did not.  Even though it was instantiating an [...]]]></description>
			<content:encoded><![CDATA[<p>Today, <a href="http://caius.name/">Caius</a> made a discovery that shocked me.  </p>
<p>He had a class, descending from ActiveRecord::Base, with a custom constructor (initialize method).  To debug it, he had the constructor raise an exception.  In the console, <code>Thingy.new(params)</code> raised the exception as expected.  But <code>wotsit.thingies.find_by_field(value)</code> did not.  Even though it was instantiating an instance of Thingy and returning it.  </p>
<p>&#8220;It must not be calling the constructor&#8221; he said.<br />
&#8220;Rubbish&#8221; said I, &#8220;it&#8217;s a constructor.  Constructors are always called.  That&#8217;s the point of them&#8221;.  </p>
<p>But as he dug deeper it certainly looked like the constructor wasn&#8217;t being called.  </p>
<p>And then he found an article explaining that you should <a href="http://blog.dalethatcher.com/2008/03/rails-dont-override-initialize-on.html">never rely</a> on things being set up on in an Active Record constructor.  Mainly because Active Record uses <code>allocate</code> to instantiate associated objects.  And what is this mysterious allocate?  Why <a href="http://whytheluckystiff.net/articles/rubyOneEightOh.html">explains it all</a>.  </p>
<p>To be honest, I&#8217;ve got mixed feelings about this.  I can see the use of &#8220;allocate&#8221; &#8211; why&#8217;s example of marshalling an object makes sense (I&#8217;m slightly less sure about the way that Active Record uses it to load associations).  But, to my mind, the definition of a constructor is &#8220;the code that is always called when an object is created&#8221;.  So maybe I should just stop thinking of <code>initialize</code> as a constructor and more as an initialiser.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/06/03/constructors-in-ruby-are-not-guaranteed-to-be-called/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/06/03/constructors-in-ruby-are-not-guaranteed-to-be-called/</feedburner:origLink></item>
		<item>
		<title>Note to self: comparing two branches in git and squashing several commits into one</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/-ju6fFZEKUM/</link>
		<comments>http://www.3hv.co.uk/blog/2009/06/02/note-to-self-comparing-two-branches-in-git-and-squashing-several-commits-into-one/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 19:49:45 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Managing Successful Projects]]></category>
		<category><![CDATA[Ruby on Rails and Software Development]]></category>
		<category><![CDATA[branches]]></category>
		<category><![CDATA[commits]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[source control]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=548</guid>
		<description><![CDATA[I always forget how to do this so I&#8217;m writing it down (especially as it&#8217;s really easy and git, as usual, makes me feel stupid as Linus is so much smarter than me).  
Suppose you&#8217;ve been working in branch X and you&#8217;re about to merge those changes into branch Y &#8230;

work in branch X [...]]]></description>
			<content:encoded><![CDATA[<p>I always forget how to do this so I&#8217;m writing it down (especially as it&#8217;s really easy and git, as usual, makes me feel stupid as Linus is so much smarter than me).  </p>
<p>Suppose you&#8217;ve been working in branch X and you&#8217;re about to merge those changes into branch Y &#8230;</p>
<ul>
<li>work in branch X and make your commits as needed</li>
<li>switch to branch Y <code>git checkout Y</code></li>
<li>compare the differences between X and Y <code>git log Y..X</code> &#8211; the order here is important; it is merge-target..merge-source</li>
<li>merge the changes from X (merge-source) into Y (merge-target) <code>git merge X</code></li>
</ul>
<p>Even better, before doing the merge, while you are still in branch X, you can squash multiple commits into a single one.  This way, branch Y, when you examine the log, has a single entry &#8220;implemented feature X&#8221;, instead of thirty-five entries all related to feature X in some way.  </p>
<ul>
<li>examine the log <code>git log</code> or even better <code>git log --pretty=oneline</code></li>
<li>choose the commit that immediately precedes the one that starts your piece of work (probably the last one before you branched to start work on feature X)</li>
<li>start an interactive rebase session &#8211; this is git-fancy-talk for picking some commits and typing a message &#8211; <code>git rebase -i THE-COMMIT-ID-OF-THE-COMMIT-YOU-SELECTED-ABOVE</code></li>
<li>Your favourite editor (or nano) will open listing the commits for feature X &#8211; edit the word &#8220;pick&#8221; to &#8220;squash&#8221; for all except the top entry, save and exit</li>
<li>Your favourite editor will open again &#8211; again showing your commit messages &#8211; add a line <em>at the top</em> stating something like &#8220;implementation of feature X&#8221; and leave the list of individual commits on separate lines below it (adding in a Fixes #123 or whatever your issue tracker demands as the last line), save and exit</li>
<li>Now if you do a <code>git log</code> you will see a single commit with a nice &#8220;implementation of feature X&#8221; log message</li>
<li>And you&#8217;re all set to merge to your master branch without cluttering its history with a long string of commit messages</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/06/02/note-to-self-comparing-two-branches-in-git-and-squashing-several-commits-into-one/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/06/02/note-to-self-comparing-two-branches-in-git-and-squashing-several-commits-into-one/</feedburner:origLink></item>
		<item>
		<title>My cron jobs and rake tasks won’t write to the Rails log file</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/CwET03h1hIM/</link>
		<comments>http://www.3hv.co.uk/blog/2009/06/01/my-cron-jobs-and-rake-tasks-wont-write-to-the-rails-log-file/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 21:34:09 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Ruby on Rails and Software Development]]></category>
		<category><![CDATA[clusters]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[logger]]></category>
		<category><![CDATA[rails]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=542</guid>
		<description><![CDATA[A project I&#8217;ve been working on was recently moved up to Rails 2.2 (Rails 2.3 migration coming soon, but we wanted to take things one step at a time).  
All the tests passed.  Poking it on the staging server worked well.  On to production and all was good.  
Time passed.  [...]]]></description>
			<content:encoded><![CDATA[<p>A project I&#8217;ve been working on was recently moved up to Rails 2.2 (Rails 2.3 migration coming soon, but we wanted to take things one step at a time).  </p>
<p>All the tests passed.  Poking it on the staging server worked well.  On to production and all was good.  </p>
<p>Time passed.  </p>
<p>Then, the app needed to be moved to a new server.  Actually to a cluster.  Slightly more nerve-wracking, but some playing around with the <a href="http://github.com/bjeanes/ghost/tree/master">ghost</a> gem and DNS settings and the deployment completed.  </p>
<p>More time passed.  </p>
<p>And then disaster struck.  Well, not disaster, but it wasn&#8217;t good.  Not at all.   </p>
<p>The app had a rake task that was cronned to run every night.  And it failed silently.  We found out the day after and I scanned the production log file looking for evidence of what went wrong.  Nowt.  It didn&#8217;t even look like the rake task had run &#8211; but it had, as I had the data in front of me.  </p>
<p>And the day after, it failed again.  Another scan of the production log revealed nothing.  Things were getting serious.  </p>
<p>I suspected the cluster deployment.  Maybe cron didn&#8217;t have permission to write to the log file, even though Passenger did.  But everything looked good on that front.  Maybe there was something else weird about the cluster setup &#8211; all the cron jobs were set to run on one of the app-servers; maybe moving it would make a difference?  </p>
<p>To test this, I opened the Rails console and started manually recreating what the rake task was doing, on a different app-server.  Which is when I noticed that script/console wasn&#8217;t writing to the production log either.  What?  </p>
<p>After a couple of hours of head scratching, I finally found out that the cluster deployment was not at fault.  In fact, it seems to be the move to Rails 2.2 that had happened many weeks before &#8211; in particular it appears that the logger object no longer auto-flushes itself after writing.  </p>
<p>We added a quick <code>Rails.logger.auto_flushing = 1</code> to an initialiser and both script/console and the rake tasks wrote to the log as expected.  Phew!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/06/01/my-cron-jobs-and-rake-tasks-wont-write-to-the-rails-log-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/06/01/my-cron-jobs-and-rake-tasks-wont-write-to-the-rails-log-file/</feedburner:origLink></item>
		<item>
		<title>Note to self: rebuilding ferret indexes when using ferret server</title>
		<link>http://feedproxy.google.com/~r/3hv/~3/xKEIyBqXR98/</link>
		<comments>http://www.3hv.co.uk/blog/2009/05/26/note-to-self-rebuilding-ferret-indexes-when-using-ferret-server/#comments</comments>
		<pubDate>Tue, 26 May 2009 21:10:44 +0000</pubDate>
		<dc:creator>Rahoul Baruah</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[ferret]]></category>
		<category><![CDATA[monit]]></category>

		<guid isPermaLink="false">http://www.3hv.co.uk/blog/?p=537</guid>
		<description><![CDATA[For some reason ferret server on a site I have been managing has been giving me a load of grief.  
I seem to have nailed it down to two problems.  
Firstly, monit only seems to like monitoring ferret server under certain circumstances.  
Secondly, the ferret indexes don&#8217;t seem to like being rebuilt. [...]]]></description>
			<content:encoded><![CDATA[<p>For some reason ferret server on a site I have been managing has been giving me a load of grief.  </p>
<p>I seem to have nailed it down to two problems.  </p>
<p>Firstly, monit only seems to like monitoring ferret server under certain circumstances.  </p>
<p>Secondly, the ferret indexes don&#8217;t seem to like being rebuilt.  </p>
<p>The first one is weird &#8230; my monit config looks like this: </p>
<pre><code>
check process ferret with pidfile /home/rails/myapp/current/log/ferret.pid
  start program = "/home/rails/myapp/current/script/ferret_server -e production start"
  as uid rails and gid rails
  stop program  = "/home/rails/myapp/current/script/ferret_server -e production stop"
  as uid rails and gid rails
  group ferret
  if failed port 9010 type TCP then restart
  if 5 restarts within 5 cycles then timeout
</code></pre>
<p>But monit often says &#8220;not monitored&#8221;.  And completely fails to restart the server if it does go down.  </p>
<p>No solution to that as yet.  </p>
<p>The second problem is even weirder.  </p>
<p>If I stop the server, then rebuild the indexes (I have a custom rake task that rebuilds all the indexes for my app) and restart, every search crashes ferret.  </p>
<p>If I rebuild the indexes while the server is running, it appears to run fine.  Why?  I have absolutely no idea.  </p>
]]></content:encoded>
			<wfw:commentRss>http://www.3hv.co.uk/blog/2009/05/26/note-to-self-rebuilding-ferret-indexes-when-using-ferret-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.3hv.co.uk/blog/2009/05/26/note-to-self-rebuilding-ferret-indexes-when-using-ferret-server/</feedburner:origLink></item>
	</channel>
</rss>
