<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/atom10full.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <title>smartbomb - Home</title>
  <id>tag:blog.smartbomb.com.au,2008:mephisto/</id>
  <generator version="0.7.3" uri="http://mephistoblog.com">Mephisto Noh-Varr</generator>
  
  <link href="http://blog.smartbomb.com.au/" rel="alternate" type="text/html" />
  <updated>2008-06-25T12:51:42Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/Smartbomb" type="application/atom+xml" /><entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-06-25:769</id>
    <published>2008-06-25T12:42:00Z</published>
    <updated>2008-06-25T12:51:42Z</updated>
    <category term="ruby" />
    <link href="http://blog.smartbomb.com.au/2008/6/25/rails-camp-three" rel="alternate" type="text/html" />
    <title>Rails Camp Three</title>
<content type="html">
            &lt;p&gt;RailsCamp 3 just finished, and it was another fantastic weekend of hacking with mates.&lt;/p&gt;


	&lt;h1&gt;what a kerfuffle!&lt;/h1&gt;


	&lt;p&gt;You’ve probably heard by now that Ben (the organiser of RailsCamp) and Kaz’s munchkin Liam came six weeks early. We’d been talking about babies coming early just the night before, 
since my son Toby was five weeks early. 
It was an eerie shock to hear that nearly the same thing had happened to Ben &amp; Kaz! Liam is doing well, but is still in hospital for a little while.&lt;/p&gt;


	&lt;p&gt;The upshot of this twist was that &lt;a href="http://glenn.davy.net.au/"&gt;Glenn Davy&lt;/a&gt; and I ended up running the camp. It was a pleasure as most of the heavy lifting had already been done by Ben.
Thanks so much to Glenn and Ben for making the camp awesome, and to everyone else for being so easy-going over the weekend.&lt;/p&gt;


	&lt;h1&gt;codings&lt;/h1&gt;


	&lt;p&gt;Lack of internet is a key feature of the RailsCamp fun.
To offset this, &lt;a href="http://lstoll.net"&gt;Lincoln Stoll&lt;/a&gt; set up a server chock full of &lt;span class="caps"&gt;VPS&lt;/span&gt;’s for hosting our apps. On top of that it served &lt;span class="caps"&gt;DNS&lt;/span&gt; and hosted gitorious.
At camp it was at http://git.railscamp.net, and now we’re back its still at http://git.railscamp.net. (Some of these apps will no doubt go across to github in time).&lt;/p&gt;


	&lt;p&gt;A bumper crop of code came home from the camp this year:&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Gitjour refactor&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/gitjour"&gt;http://git.railscamp.net/projects/gitjour&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;A group of guys made their dissatisfaction with the current gitjour implementation manifest by refactoring it, waay into early saturday morning.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Gitnotify&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Broadcast a growl notification each time you commit to git.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Gitman&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/gitman"&gt;http://git.railscamp.net/projects/gitman&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Manage your git sharing, simply. By &lt;a href="http://mike.bailey.net.au/"&gt;Mike Bailey&lt;/a&gt;&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Swords&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/swords"&gt;http://git.railscamp.net/projects/swords&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;A great start on a thesaurus based crossword generator. It has ascii and web interfaces.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Duke&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/duke"&gt;http://git.railscamp.net/projects/duke&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;The return of the network jukebox. Gaming the duke voting system provided plenty of fun for all.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://ducknewmedia.com.au/"&gt;Myles Byrne&lt;/a&gt; and I were duke’s latest developers (everyone works on duke, some time). I failed to provide events for Myles, and I’m sorry.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;bit-tags&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/bit-tags"&gt;http://git.railscamp.net/projects/bit-tags&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Taggable snippets by the Brisbane boys.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;iShare&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/ishare"&gt;http://git.railscamp.net/projects/ishare&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;An app for letting know what you’d like to hear or talk about at railscamp!&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;twonklist&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/twonklist"&gt;http://git.railscamp.net/projects/twonklist&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;An anti-social networking application.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Twetter&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://git.railscamp.net/projects/twetter"&gt;http://git.railscamp.net/projects/twetter&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;A local twitter. Linc pointed twitter.com at twetter so that everyone’s Twitterific &lt;strong&gt;just worked.&lt;/strong&gt; &lt;a href="http://blog.allen.com.au/2008/6/24/rails-camp-the-third"&gt;Matta writes about it here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Max dropped in and wrote up a Flex based client, too.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;starjour&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;&lt;a href="http://github.com/lachie/starjour/tree/master"&gt;http://github.com/lachie/starjour/tree/master&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I did some work on refactoring starjour. Still not really sure where this app is going, but 
it &lt;em&gt;was&lt;/em&gt; good to see is list full of *jour services.&lt;/p&gt;


	&lt;p&gt;If I’ve forgotten any projects, let me know.&lt;/p&gt;


	&lt;h1&gt;jq&lt;/h1&gt;


	&lt;p&gt;I gave a talk on jQuery, which was a bit of a shamozzle as my version of firebug wasn’t playing with firefox 3. Preparation? Next time I suppose.
Thanks to Hugh Evans for having a working ffx and some elegant jq code to show off.&lt;/p&gt;


	&lt;h1&gt;feedback&lt;/h1&gt;


	&lt;p&gt;If you have some feedback on the camp, please let me know: lachie (at) this domain.&lt;/p&gt;


	&lt;p&gt;One thing I’d like to see is some more emphasis on family at RailsCamp. &lt;a href="http://brodaigh.com/"&gt;Brodaigh&lt;/a&gt; brought her daughter Crystal to this one and Lone and I brought Toby to the first one.
It adds a mellowing element to the camps that I really enjoy. And, I want a chance to beat Crystal at Set.&lt;/p&gt;


	&lt;h1&gt;saving the day&lt;/h1&gt;


	&lt;p&gt;When people started leaving on Monday morning, we hit a problem: someone had inadvertently taken &lt;a href="http://www.moment.com.au/"&gt;Phil Oye’s&lt;/a&gt; bag.&lt;/p&gt;


	&lt;p&gt;After we’d finished tidying up and had hit McDonalds, I got a Twitter direct message on my phone from &lt;a href="http://drnicwilliams.com/"&gt;Dr Nic&lt;/a&gt; “what’s your ph num? we have someone’s black bag @ airport.”&lt;/p&gt;


	&lt;p&gt;I was able to put Phil in contact with Greg Fairbrother and it all ended happily ever after.&lt;/p&gt;


	&lt;p&gt;Twitter &lt;span class="caps"&gt;FTW&lt;/span&gt;&lt;/p&gt;


	&lt;h1&gt;Summer 08 ? Winter 09 ?&lt;/h1&gt;


	&lt;p&gt;So who’s going to step up next? Railscamp happens where ever someone organises it. It may be a structure-less weekend, but its still non-trivial to set one up 
If you think you’d like to give it a go, let me know and I’ll put you in touch with people who’ve done it before. lachie (at) this domain.&lt;/p&gt;


	&lt;p&gt;The guys from Brisbane are keen to put on a camp, probably in Winter 2009.&lt;/p&gt;


	&lt;p&gt;Who wants to organise an event for Summer 2008/9 ?&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/319703232" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-05-22:740</id>
    <published>2008-05-22T03:49:00Z</published>
    <updated>2008-05-22T03:52:45Z</updated>
    <link href="http://blog.smartbomb.com.au/2008/5/22/my-first-redbubble-shirt" rel="alternate" type="text/html" />
    <title>my first redbubble shirt</title>
<content type="html">
            &lt;p&gt;A couple of years ago, I designed and hand-printed three t-shirts.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/lachie/3128397/" title="DSCN3409 by lachie, on Flickr"&gt;&lt;img src="http://farm1.static.flickr.com/1/3128397_c10fe739b1_t.jpg" height="75" alt="DSCN3409" width="100" /&gt;&lt;/a&gt;
&lt;a href="http://www.flickr.com/photos/lachie/6112157/" title="crabjam shirt by lachie, on Flickr"&gt;&lt;img src="http://farm1.static.flickr.com/6/6112157_17f6b70125_t.jpg" height="100" alt="crabjam shirt" width="69" /&gt;&lt;/a&gt;
&lt;a href="http://www.flickr.com/photos/lachie/3452603/" title="ninja traced by lachie, on Flickr"&gt;&lt;img src="http://farm1.static.flickr.com/2/3452603_f9117a5b95_t.jpg" height="100" alt="ninja traced" width="74" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;It was a lot of effort, mainly due to having to hand-cut the stencils out of overhead projector slides. The quality was never quite up to snuff. And the paint was smelly and extremely messy. Despite all that, &lt;em&gt;it was a blast&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;So now that I have a bit of time off, I find myself wanting to do some designs again… This time I’m eschewing the heady chemical aroma of fabric paint and using &lt;a href="http://www.redbubble.com/"&gt;Redbubble&lt;/a&gt;, a &lt;a href="http://en.wikipedia.org/wiki/The_Long_Tail"&gt;long tail&lt;/a&gt; publishing business based in Melbourne. They’ll print cards, prints and &lt;strong&gt;shirts&lt;/strong&gt; from your artwork.&lt;/p&gt;


	&lt;p&gt;They charge a reasonable base price, over which you can mark up whatever profit you desire. Selling costs nothing, so at the very least you can get your own designs printed for only $21. Niice.&lt;/p&gt;


	&lt;p&gt;On top of that, the site is really nicely designed and runs on Rails. Our #roro friends &lt;a href="http://rhnh.net/"&gt;Xavier Shay&lt;/a&gt; and &lt;a href="http://justinfrench.com/"&gt;Justin French&lt;/a&gt; work there.&lt;/p&gt;


	&lt;p&gt;so anyway:&lt;/p&gt;


	&lt;h1&gt;buy my tshirt!&lt;/h1&gt;


	&lt;p&gt;&lt;img src="http://images-0.redbubble.com/img/clothing/bodycolor:gold/size:large/style:mens/view:preview/1169263-4-schr-dingers-bird.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.redbubble.com/people/lachiec/clothing/1169263-4-schr-dingers-bird"&gt;Here&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;If you don’t get it, have a clue: http://twitter.com&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/295537307" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-04-19:622</id>
    <published>2008-04-19T23:59:00Z</published>
    <updated>2008-04-19T23:59:48Z</updated>
    <link href="http://blog.smartbomb.com.au/2008/4/19/white-blood-cells" rel="alternate" type="text/html" />
    <title>white blood cells</title>
<content type="html">
            &lt;p&gt;We have such overwhelming abundance as a society; that we continue to squander it brings me close to despair. Acting only as a diluted 2020 herd is abdicating our responsibility.&lt;/p&gt;


	&lt;p&gt;We’re the top of the pile; the assumption of personal responsibility stands as the only mechanism left to us to achieve the things we &lt;em&gt;need&lt;/em&gt; to.&lt;/p&gt;


	&lt;p&gt;The education system will never tailor itself to &lt;em&gt;your&lt;/em&gt; kids. You will need to shoulder the burden of education yourself.&lt;/p&gt;


	&lt;p&gt;The bulk of society will likely &lt;em&gt;never&lt;/em&gt; grasp technology as fully as we do. Its up to us to promulgate and fulfill its promise.&lt;/p&gt;


	&lt;p&gt;We’re not helpless motes in the plasma of society. We’re the &lt;a href="http://en.wikipedia.org/wiki/White_blood_cell#Overview_table"&gt;white blood cells&lt;/a&gt;.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/273804806" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-02-19:277</id>
    <published>2008-02-19T06:55:00Z</published>
    <updated>2008-03-11T02:00:38Z</updated>
    <category term="ruby" />
    <link href="http://blog.smartbomb.com.au/2008/2/19/merb-tips" rel="alternate" type="text/html" />
    <title>Merb tips</title>
<content type="html">
            &lt;p&gt;So there’s only one at the moment, but i really wanted to write this down:&lt;/p&gt;


	&lt;h1&gt;0.5.x make the development logger log &lt;span class="caps"&gt;DEBUG&lt;/span&gt; messages…&lt;/h1&gt;


	&lt;p&gt;Put this in &lt;code&gt;Merb.root/config/environments/development.yml&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="yaml"&gt;:log_level: DEBUG&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;0.9.x freezing gems&lt;/h1&gt;


The way of installing the latest merb release is 
&lt;pre&gt;&lt;code class="bash"&gt;$ cd to/your/app
$ gem install merb -i gems --source=http://merbivore.com&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Unfortunately, this command won’t install merb’s dependencies as it won’t be able to look inside the normal gems repository on rubyforge.&lt;/p&gt;


This should do the trick though
&lt;pre&gt;&lt;code class="bash"&gt;$ cd to/your/app
$ gem install merb -i gems --source=http://merbivore.com --source=http://gems.rubyforge.org&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Yay!&lt;/p&gt;


	&lt;p&gt;(Note that this is only a problem while the merb gems aren’t pushed to rubyforge).&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/237400398" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-02-11:262</id>
    <published>2008-02-11T10:32:00Z</published>
    <updated>2008-02-11T10:41:23Z</updated>
    <link href="http://blog.smartbomb.com.au/2008/2/11/quicksilver-javascript" rel="alternate" type="text/html" />
    <title>quicksilver javascript</title>
<content type="html">
            &lt;h1&gt;point one&lt;/h1&gt;


	&lt;p&gt;&lt;span&gt;&lt;a href="http://www.blacktree.com/"&gt;Quicksilver&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;


	&lt;h1&gt;point two&lt;/h1&gt;


	&lt;p&gt;I want to &lt;em&gt;act without doing&lt;/em&gt; in web apps.&lt;/p&gt;


	&lt;h1&gt;point three&lt;/h1&gt;


	&lt;p&gt;&lt;a href="http://rails-oceania.googlecode.com/svn/lachiecox/qs_score/trunk/qs_score.js"&gt;qs_score.js&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://smartbomb.com.au/qs_score/qs_score.html"&gt;For example&lt;/a&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/233070157" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-02-01:208</id>
    <published>2008-02-01T12:42:00Z</published>
    <updated>2008-02-01T12:49:26Z</updated>
    <link href="http://blog.smartbomb.com.au/2008/2/1/i-love-me-some-source" rel="alternate" type="text/html" />
    <title>I love me some source</title>
<content type="html">
            &lt;p&gt;I don’t know if its because I’m nosy, or because I’m a control freak, or perhaps both, but I really do like to read the source code. It occurs to me that this is probably why I feel so at home in the open source world.&lt;/p&gt;


	&lt;p&gt;As much as I like something like Cocoa, it pains me not to be able to trace problems all the way down the stack. Even java solved this problem by shipping with its own source.&lt;/p&gt;


	&lt;p&gt;Proclivities aside, I really like source, and am always looking for ways to make it easier to &lt;em&gt;get at&lt;/em&gt;. &lt;code&gt;cd /usr/lib/ruby/gems/1.8/gems&lt;/code&gt; gets old quick.&lt;/p&gt;


	&lt;p&gt;I started with this little &lt;em&gt;cough&lt;/em&gt; &lt;a href="http://drnic.tumblr.com/post/166472"&gt;gem from Dr Nic&lt;/a&gt;. Integrating it with my shell, I could now type&lt;/p&gt;


&lt;pre&gt;&lt;code class=""&gt;$ gems activerecord&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;and up pops the activerecord gem in Textmate. So some new releases of activerecord came out, and suddenly my naive script is giving me the old version. Without looking too far into it I added gem requirement support so that I could type&lt;/p&gt;


&lt;pre&gt;&lt;code class=""&gt;$ gems activerecord '&gt;=2'&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;and get a recent activerecord in Textmate. As good as this is, I was really after something with &lt;em&gt;less typing&lt;/em&gt; and smarter pants. Well tonight I cracked it and I thought I’d open the source:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;#!/usr/bin/env ruby

require ENV['TM_SUPPORT_PATH']+"/lib/ui" 
require 'rubygems'

gems = Gem.source_index.latest_specs.collect {|spec| spec.full_name}.sort

TextMate::UI.request_item(:title =&gt; 'open a gem', :items =&gt; gems) do |selected_gem|
    gem_path = Gem.source_index.specification(selected_gem).full_gem_path
    %x{open -a TextMate #{gem_path}}
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Honestly, that’s it! Bung that in a command using Textmate’s Bundle Editor and assign it a key (I gave it cmd-shift-G, as I don’t regularly search backwards).&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://smartbomb.com.au/assets/2008/2/1/open_a_gem-1.jpg" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;Double click on one and you’re golden… neat.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543434" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2008-01-27:166</id>
    <published>2008-01-27T02:33:00Z</published>
    <updated>2008-01-27T02:34:09Z</updated>
    <link href="http://blog.smartbomb.com.au/2008/1/27/de-bulk-your-gem-threshold" rel="alternate" type="text/html" />
    <title>de-bulk your gem threshold</title>
<content type="html">
            &lt;p&gt;At &lt;a href="http://workatjelly.com/"&gt;Jelly Sydney&lt;/a&gt; last Friday, I went to see if my &lt;a href="http://merbivore.com"&gt;merb&lt;/a&gt; gems were up to date. You know:&lt;/p&gt;


&lt;pre&gt;&lt;code class="bash"&gt;$ gem list --remote

*** REMOTE GEMS ***

Updating metadata for 114 gems from http://gems.rubyforge.org
...&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Each dot was taking aages, and there were to be one hundred and fourteen of the blighters!&lt;/p&gt;


	&lt;h2&gt;In a nutshell&lt;/h2&gt;


	&lt;p&gt;The rubygem server seemed to be having issues serving up incremental metadata. Until the rubygems server got back on its feet, I set my bulk threshold to a lower value:&lt;/p&gt;


&lt;pre&gt;&lt;code class="bash"&gt;echo :bulk_threshold: 1 &gt;&gt; ~/.gemrc&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;I won’t leave it there, because it could impact the overall rubygem system’s performance (well maybe if everyone decided to do this all the time).&lt;/p&gt;


	&lt;h2&gt;Detailure&lt;/h2&gt;


	&lt;p&gt;There were about seven peoples on the &lt;a href="http://nerfpalace.org/"&gt;NerfPalace Wifi&lt;/a&gt; by this stage, so it was only natural to ask:&lt;/p&gt;


	&lt;p&gt;Lachie: “Hey &lt;a href="http://toolmantim.com"&gt;Tim&lt;/a&gt;, is the network slow?”&lt;/p&gt;


	&lt;p&gt;Tim: “Nah aah, girlfriend. You slow. Or yo gems are slow, biatch.”&lt;/p&gt;


	&lt;p&gt;Well! It turns out that Tim had noticed the same thing and had started digging into the very source code of gems in search of an answer.&lt;/p&gt;


	&lt;h2&gt;Teh Pwobwem&lt;/h2&gt;


	&lt;p&gt;In order not to overtax the rubygem servers’ bandwidth, gem first finds out how many of its cached metadata are out of date. If the number is greater than an arbitrary threshold, it performs a bulk update in which &lt;strong&gt;all&lt;/strong&gt; the metadata is updated at once.&lt;/p&gt;


	&lt;p&gt;If the number is below the threshold, each metadatum is fetched and updated individually (&lt;strong&gt;incrementally&lt;/strong&gt; you might say).&lt;/p&gt;


	&lt;p&gt;By default, this number is 1000. Say each update was taking a second and there were 999 gems to update, this process would take more than a quarter of an hour. Presumably the average case is much better than this, but on Friday, each increment of the update was taking &lt;em&gt;forever&lt;/em&gt;.&lt;/p&gt;


	&lt;p&gt;The complete source_cache is currently ~850k gzipped. Although in aggregate this could cost the rubygems people a fair bit of bandwidth, it would never take 15 minutes on today’s broadband.&lt;/p&gt;


	&lt;p&gt;What we needed was some way of forcing the bulk update, which at the time was much faster than the alternative. The mechanism for this is not very clear, so we got by by hacking the code.&lt;/p&gt;


	&lt;h2&gt;&lt;span class="caps"&gt;HOWTO&lt;/span&gt;&lt;/h2&gt;


	&lt;p&gt;Thankfully, there is a better way or changing the threhold! Although its not well documented or, well, documented at all, you can set the &lt;code&gt;bulk_threshold&lt;/code&gt; variable in the .gemrc file kept in your home directory. Its &lt;span class="caps"&gt;YAML&lt;/span&gt;, y’know:&lt;/p&gt;


&lt;pre&gt;&lt;code class="yaml"&gt;:bulk_threshold: 1&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;See that colon out the front of the bulk_threshold key? Its because its a symbol once it gets inside the ruby.&lt;/p&gt;


	&lt;p&gt;As I mentioned above, its probably not good manners to leave your threshold at 1, since the authors have built the system in a certain way (even if its not always optimal) and we’re not paying the rubygem bandwidth fees. Just think, it’d be terrible for The Authors to chuck a Zed and shut rubygems down!&lt;/p&gt;


	&lt;p&gt;Hooray for Rubygems!&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543435" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-09-30:67</id>
    <published>2007-09-30T06:55:00Z</published>
    <updated>2007-09-30T07:06:12Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/9/30/roro-sydney-talk-drying-up-your-views" rel="alternate" type="text/html" />
    <title>RORO Sydney Talk - DRYing up your views</title>
<content type="html">
            &lt;p&gt;Last &lt;a href="http://rubyonrails.com.au/2007/9/4/sydney-september-2007-meetup"&gt;&lt;span class="caps"&gt;RORO&lt;/span&gt; Sydney meetup&lt;/a&gt; I did a talk on DRYing up your views.&lt;/p&gt;


&amp;lt;object id="viddler" height="370" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437"&gt;&amp;lt;param name="movie" value="http://www.viddler.com/player/4ff82d29/" /&gt;&amp;lt;param name="allowScriptAccess" value="always" /&gt;&amp;lt;param name="allowFullScreen" value="true" /&gt;&amp;lt;embed name="viddler" allowfullscreen="true" type="application/x-shockwave-flash" src="http://www.viddler.com/player/4ff82d29/" allowscriptaccess="always" height="370" width="437"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;

	&lt;p&gt;I was very pleased with how it went – this really does get easier with practice! The first couple of slides were dropped, but you didn’t miss much of note :)&lt;/p&gt;


	&lt;p&gt;We’re really starting to refine the workflow for recording talks and I’m planning a write up of our experiences so far.&lt;/p&gt;


	&lt;p&gt;Big thanks to Tim Lucas for putting this months’ ‘casts together.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543436" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-09-16:63</id>
    <published>2007-09-16T04:40:00Z</published>
    <updated>2007-09-19T07:48:25Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/9/16/logeye-a-rails-log-gui" rel="alternate" type="text/html" />
    <title>Logeye - a rails log gui</title>
<content type="html">
            &lt;p&gt;The Rails log is a very valuable resource. It contains a lot of information and its relatively easy to read.&lt;/p&gt;


	&lt;p&gt;However, I find that It doesn’t take long to get pretty sick of scrolling around, visually decoding, not to mention that the ansi covered &lt;span class="caps"&gt;SQL&lt;/span&gt; is a pain.&lt;/p&gt;


	&lt;p&gt;Logeye is my itch-scratcher to make it better and more useful. You point it at either your &lt;span class="caps"&gt;RAILS&lt;/span&gt;_ROOT or directly at a log file, and watch the requests flow past as you develop your app.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/lachie/1406167948/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1430/1406167948_57c8d136dd.jpg" height="500" alt="logeye 0.3.5 screenshot" width="380" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;h1&gt; Download&lt;/h1&gt;


	&lt;p&gt;&lt;a href="http://rails-oceania.googlecode.com/files/Logeye-0.3.6.zip"&gt;&lt;img src="http://blog.smartbomb.com.au/assets/2007/9/16/icon_128.jpg" height="128" alt="logeye icon" width="128" /&gt;&lt;br /&gt;
Logeye 0.3.6&lt;/a&gt;&lt;/p&gt;


	&lt;h1&gt;Features and problems&lt;/h1&gt;


	&lt;ul&gt;
	&lt;li&gt;In the open dialog you select &lt;code&gt;RAILS_ROOT&lt;/code&gt;, not the log file itself.&lt;/li&gt;
		&lt;li&gt;Double click a log entry to open the corresponding controller file in your editor (set in preferences)&lt;/li&gt;
		&lt;li&gt;You can set window alpha, and make the windows float above other apps (set in preferences)&lt;/li&gt;
		&lt;li&gt;The zoom + does something useful.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h1&gt;Upcoming Features&lt;/h1&gt;


	&lt;ul&gt;
	&lt;li&gt;filtering, searching&lt;/li&gt;
		&lt;li&gt;&lt;del&gt;smarter opening.&lt;/del&gt;&lt;/li&gt;
		&lt;li&gt;refined log details view with visual distinction for each kind of line.&lt;/li&gt;
		&lt;li&gt;easy copying of &lt;span class="caps"&gt;SQL&lt;/span&gt;.&lt;/li&gt;
		&lt;li&gt;easy opening of files referred to in backtraces.&lt;/li&gt;
		&lt;li&gt;backtrace filtering.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h1&gt;update 1 2007/08/19&lt;/h1&gt;


	&lt;p&gt;Released Logeye 0.3&lt;/p&gt;


changes:
	&lt;ul&gt;
	&lt;li&gt;refined look&lt;/li&gt;
		&lt;li&gt;ability to open log files directly&lt;/li&gt;
		&lt;li&gt;parsing of intra-request fluff&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h1&gt;update 2 2007/08/19&lt;/h1&gt;


	&lt;p&gt;Released Logeye 0.3.5&lt;/p&gt;


changes:
	&lt;ul&gt;
	&lt;li&gt;now opens nested controllers&lt;/li&gt;
		&lt;li&gt;it remembers which logs it was tailing last time you had it open and reopens them&lt;/li&gt;
		&lt;li&gt;more looks&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Logeye 0.3.6 is a minor bugfix&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543437" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-08-29:49</id>
    <published>2007-08-29T04:49:00Z</published>
    <updated>2007-08-29T05:14:33Z</updated>
    <category term="hornsby" />
    <category term="ruby" />
    <category term="tools" />
    <link href="http://blog.smartbomb.com.au/2007/8/29/hornsby" rel="alternate" type="text/html" />
    <title>Hornsby</title>
<summary type="html">&lt;p&gt;A while back I gave a talk at the Sydney Rails Group about Hornsby, my plugin for example based modeling. I always meant to release it, but as it got a work out it never really gave me the satisfaction I craved.&lt;/p&gt;


	&lt;p&gt;Recently, there was an &lt;a href="http://errtheblog.com/post/7708"&gt;Err post&lt;/a&gt; about layering a &lt;span class="caps"&gt;DSL&lt;/span&gt; over &lt;a href="http://code.google.com/p/fixture-scenarios/"&gt;fixture scenarios&lt;/a&gt;. The idea of an expressive &lt;span class="caps"&gt;DSL&lt;/span&gt; for setting up test or spec data was super, but I had trouble getting it to work with &lt;a href="http://rspec.rubyforge.org"&gt;RSpec&lt;/a&gt;. Oh and fixtures? Why cling to these much maligned giblets of yaml?&lt;/p&gt;


	&lt;p&gt;So here’s Hornsby, reborn: A Scenario Builder without the fixture pain.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;A while back I gave a talk at the Sydney Rails Group about Hornsby, my plugin for example based modeling. I always meant to release it, but as it got a work out it never really gave me the satisfaction I craved.&lt;/p&gt;


	&lt;p&gt;Recently, there was an &lt;a href="http://errtheblog.com/post/7708"&gt;Err post&lt;/a&gt; about layering a &lt;span class="caps"&gt;DSL&lt;/span&gt; over &lt;a href="http://code.google.com/p/fixture-scenarios/"&gt;fixture scenarios&lt;/a&gt;. The idea of an expressive &lt;span class="caps"&gt;DSL&lt;/span&gt; for setting up test or spec data was super, but I had trouble getting it to work with &lt;a href="http://rspec.rubyforge.org"&gt;RSpec&lt;/a&gt;. Oh and fixtures? Why cling to these much maligned giblets of yaml?&lt;/p&gt;


	&lt;p&gt;So here’s Hornsby, reborn: A Scenario Builder without the fixture pain.&lt;/p&gt;
&lt;p&gt;Scenarios look like:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;scenario :apple do
  @apple = Fruit.create! :species =&gt; 'apple'
end

scenario :orange do
  @orange = Fruit.create! :species =&gt; 'orange'
end

scenario :fruitbowl =&gt; [:apple,:orange] do
  @fruitbowl = FruitBowl.create! :fruit =&gt; [@apple,@orange]
end

scenario :kitchen =&gt; :fruitbowl do
  @kitchen = Kitchen.create! :fruitbowl =&gt; @fruitbowl
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;By default, these are loaded from &lt;code&gt;RAILS_ROOT/spec/hornsby_scenarios.rb&lt;/code&gt;&lt;/p&gt;


	&lt;p&gt;...and you use them in specs like:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;describe Fruit, "@apple" do
  before do
    hornsby_scenario :apple
  end

  it "should be an apple" do
    @apple.species.should == 'apple'
  end
end

describe FruitBowl, "with and apple and an orange" do
  before do
    hornsby_scenario :fruitbowl
  end

  it "should have 2 fruits" do
    @fruitbowl.should have(2).fruit
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;Setup&lt;/h1&gt;


	&lt;p&gt;Install the plugin:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
./script/plugin install http://rails-oceania.googlecode.com/svn/lachiecox/hornsby
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Or piston:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
piston import http://rails-oceania.googlecode.com/svn/lachiecox/hornsby vendor/plugins/hornsby
&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Add the following to &lt;code&gt;spec_helper.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;# by default this loads scenarios from RAILS_ROOT/spec/hornsby_scenarios.rb
Hornsby.load

Spec::Runner.configure do |config|
  ...

  config.include(HornsbySpecHelper)
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;Advanced Usage&lt;/h1&gt;


	&lt;p&gt;Its just ruby, right? So go nuts:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;1.upto(9) do |i|
  scenario("user_#{i}") do
    user = User.create! :name =&gt; "user#{i}" 
    instance_variable_set("@user_#{i}",user)
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;Rake&lt;/h1&gt;


	&lt;p&gt;If you’d like simply to load your scenarios into a database, use the rake task like so:&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
$ rake hornsby:scenario RAILS_ENV=test SCENARIO=fruitbowl
&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;&lt;span class="caps"&gt;TODO&lt;/span&gt;&lt;/h1&gt;


	&lt;ul&gt;
	&lt;li&gt;Make transactional for speed.&lt;/li&gt;
		&lt;li&gt;Add scenario namespaces for better organisation.&lt;/li&gt;
		&lt;li&gt;Detect scenario cycles.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;h1&gt;Credits&lt;/h1&gt;


	&lt;p&gt;&lt;a href="mailto:lachie@smartbomb.com.au"&gt;Lachie Cox&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;The code is based on Err’s code found in &lt;a href="http://errtheblog.com/post/7708"&gt;this post&lt;/a&gt;&lt;/p&gt;


	&lt;h1&gt;License&lt;/h1&gt;


	&lt;p&gt;&lt;span class="caps"&gt;MIT&lt;/span&gt;, see &lt;span class="caps"&gt;LICENCE&lt;/span&gt;&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543438" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-08-27:48</id>
    <published>2007-08-27T13:07:00Z</published>
    <updated>2007-08-27T23:27:01Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/8/27/hax-day-at-lachie-s" rel="alternate" type="text/html" />
    <title>Hax Day at Lachie's</title>
<summary type="html">&lt;p&gt;On the 18th of August I hosted a &lt;a href="http://rubyonrails.com.au"&gt;RoRo&lt;/a&gt; Hax day. 13 people turned up bright and early (for a Saturday) and got hacking on diverse Rails and Ruby stuff.
&lt;a href="http://www.flickr.com/photos/lachie/1181198913/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1012/1181198913_306427a889_m.jpg" height="158" alt="Hax Day" width="240" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Lone baked up a storm all day, fueling some great work.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;On the 18th of August I hosted a &lt;a href="http://rubyonrails.com.au"&gt;RoRo&lt;/a&gt; Hax day. 13 people turned up bright and early (for a Saturday) and got hacking on diverse Rails and Ruby stuff.
&lt;a href="http://www.flickr.com/photos/lachie/1181198913/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1012/1181198913_306427a889_m.jpg" height="158" alt="Hax Day" width="240" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Lone baked up a storm all day, fueling some great work.&lt;/p&gt;
&lt;h1&gt;seesaw&lt;/h1&gt;


	&lt;p&gt;As you’ve probably heard already, &lt;a href="http://blog.allen.com.au/2007/8/21/seesaw-restarting-your-mongrels-with-zero-downtime"&gt;Matt&lt;/a&gt; and &lt;a href="http://synaphy.com.au/2007/8/20/seesaw"&gt;Max&lt;/a&gt; built a sweet little gem called seesaw. It allows zero-downtime, zero-request loss restarting of mongrel clusters. They put their heads together and wrought it before our eyes. I don’t think they noticed anything but the code all day :)&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/lachie/1182056976/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1099/1182056976_b2e03a9759_m.jpg" height="158" alt="Hax Day - team seesaw" width="240" /&gt;&lt;/a&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code&gt;
gem install seesaw
&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;javascripter&lt;/h1&gt;


	&lt;p&gt;&lt;a href="http://the.railsi.st/2007/8/22/javascripter-organize-your-javascript"&gt;Pat&lt;/a&gt; knocked up a javascript version of his “Styler” plugin. It allows you to include controller- or action-specific javascript in your views. Very useful stuff, as it can add another dimension to your javascripting, and the polish you apply to them.&lt;/p&gt;


	&lt;h1&gt;numbr5&lt;/h1&gt;


	&lt;p&gt;&lt;code&gt;numbr5&lt;/code&gt; got some love from Martin and Harry. They added&lt;/p&gt;


	&lt;table&gt;
		&lt;tr&gt;
			&lt;td&gt; &lt;strong&gt;command&lt;/strong&gt; &lt;/td&gt;
			&lt;td&gt; &lt;strong&gt;action&lt;/strong&gt; &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; &lt;code&gt;?ri [term]&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; look up term with &lt;code&gt;ri&lt;/code&gt;, n5 will send a pm to you with the results. &lt;/td&gt;
		&lt;/tr&gt;
		&lt;tr&gt;
			&lt;td&gt; &lt;code&gt;?bs [someone]&lt;/code&gt; &lt;/td&gt;
			&lt;td&gt; ahem, bitchslap &lt;code&gt;someone&lt;/code&gt;, you know, when you need to. &lt;/td&gt;
		&lt;/tr&gt;
	&lt;/table&gt;




	&lt;h1&gt;Duke&lt;/h1&gt;


	&lt;p&gt;Our perennial favourite web based dukebox “duke” was dusted off by Nick and Dylan, and taught to sing. Well almost. They tried to get it using &lt;a href="http://raop.rubyforge.org/"&gt;net/raop&lt;/a&gt; but the new airport expresses weren’t really bedded down. Then icecast was attempted. Next Hax day, eh boys?&lt;/p&gt;


	&lt;h1&gt;odds and ends&lt;/h1&gt;


	&lt;p&gt;I made a few tweaks to &lt;a href="http://faces.rubyonrails.com.au"&gt;roro faces&lt;/a&gt;, while other guys just soaked up the knowledge, vibe and brownies.&lt;/p&gt;


	&lt;h1&gt;afterword&lt;/h1&gt;


	&lt;p&gt;Some guys stayed around for lovely curry made by Lone.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://www.flickr.com/photos/lachie/1181196651/" title="Photo Sharing"&gt;&lt;img src="http://farm2.static.flickr.com/1183/1181196651_3286d93721_m.jpg" height="158" alt="Hax Day - the stayers" width="240" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;We’re hoping to have many more Hax Days over the coming months, and I think they’ll become a catalyst for more and more cool, useful stuff.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543439" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-08-12:33</id>
    <published>2007-08-12T05:26:00Z</published>
    <updated>2007-08-12T05:30:25Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/8/12/patrick-crowley-at-roro-sydney" rel="alternate" type="text/html" />
    <title>Patrick Crowley at roro Sydney</title>
<content type="html">
            &lt;p&gt;Well whaddaya know? The second roro Sydney July presentation video has dropped. This time it’s Patrick Crowley from SD Ruby, San Diego talking about his two latest plugins, Headliner and Styler&lt;/p&gt;


&amp;lt;object id="viddler" height="370" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437"&gt;&amp;lt;param name="movie" value="http://www.viddler.com/player/60686700/" /&gt;&amp;lt;param name="allowScriptAccess" value="always" /&gt;&amp;lt;param name="allowFullScreen" value="true" /&gt;&amp;lt;embed name="viddler" allowfullscreen="true" type="application/x-shockwave-flash" src="http://www.viddler.com/player/60686700/" allowscriptaccess="always" height="370" width="437"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543441" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-08-11:31</id>
    <published>2007-08-11T12:39:00Z</published>
    <updated>2007-08-11T12:42:02Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/8/11/airbed-making-camping-restful" rel="alternate" type="text/html" />
    <title>airbed: making camping restful.</title>
<summary type="html">&lt;p&gt;“Phat models &amp; skinny controllers” is the new catch-phrase of RESTful rails. Of course, in the name of small corèdness, there’s no default implementation of the aforementioned skinny controller, their monotonous commonality notwithstanding.&lt;/p&gt;


	&lt;p&gt;Camping’s controllers are willfully simpler than rails.&lt;/p&gt;


	&lt;p&gt;Luke Redpath’s &lt;a href="http://www.lukeredpath.co.uk/2007/2/2/refactoring-rest-searching-for-an-abstraction"&gt;restful_exposure&lt;/a&gt; provides a flexible implementation for skinny controllers. The implementation however, gives me the chills. I feel that its willfully complex.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://rails-oceania.rubyforge.org/airbed/"&gt;Airbed&lt;/a&gt; is my response to these problems, for camping.&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;“Phat models &amp; skinny controllers” is the new catch-phrase of RESTful rails. Of course, in the name of small corèdness, there’s no default implementation of the aforementioned skinny controller, their monotonous commonality notwithstanding.&lt;/p&gt;


	&lt;p&gt;Camping’s controllers are willfully simpler than rails.&lt;/p&gt;


	&lt;p&gt;Luke Redpath’s &lt;a href="http://www.lukeredpath.co.uk/2007/2/2/refactoring-rest-searching-for-an-abstraction"&gt;restful_exposure&lt;/a&gt; provides a flexible implementation for skinny controllers. The implementation however, gives me the chills. I feel that its willfully complex.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://rails-oceania.rubyforge.org/airbed/"&gt;Airbed&lt;/a&gt; is my response to these problems, for camping.&lt;/p&gt;
&lt;p&gt;First of all, Airbed performs a task similar to Rails’ RESTful routes. That is, requests made with &lt;span class="caps"&gt;HTTP&lt;/span&gt; verbs (GET, &lt;span class="caps"&gt;POST&lt;/span&gt;, PUT and &lt;span class="caps"&gt;DELETE&lt;/span&gt;) are mapped onto the CRUDdy actions: list, show, create, update, delete, plus those two also-rans new and edit (sort of).&lt;/p&gt;


	&lt;p&gt;The CRUDdy actions all have default implementations, using naming conventions to make it fly. To make overriding the defaults generally unnecessary, options can be passed, and various hooks are called during processing.&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;PUT&lt;/span&gt; and &lt;span class="caps"&gt;DELETE&lt;/span&gt; are not commonly supported by browsers: they’re faked in more or less the same way that Rails does, by adding a _verb parameter to requests.&lt;/p&gt;


	&lt;h2&gt;a simple example&lt;/h2&gt;


	&lt;p&gt;The doco is coming along as the behaviour’s being refined, but for now a simplified example is most eloquent. The full example is in airbed at &lt;code&gt;examples/faces.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;Camping.goes :Faces

module Faces
  module Models
    class Person &amp;lt; Base; end
  end

  module Controllers
    include Airbed::Resources

    class Index &amp;lt; R '/'
      def get
        redirect People
      end
    end

    class People &amp;lt; Resource Models::Person
      def after_modification(instance)
        redirect(People)
      end
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;View names are also inferred from naming conventions:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;module Faces
  module Views
    # TODO make this work by including Airbed::Views
    def form(options={})
      verb = method = options[:method] || :post
      options[:method] = :post unless [:get,:post].include? method.to_sym

      tag!(:form, options) {
        input(:type =&gt; 'hidden', :name =&gt; '_verb', :value =&gt; verb)
        yield
      }
    end

    def _button(text,href,method=:post)
      form(:action =&gt; href, :method =&gt; method) {
        input :type =&gt; 'submit', :value =&gt; text
      }
    end

    def list_people
      h1 'ppl!'
      ul {
        @people.each {|person|
          li { a person.name, :href =&gt; R(People,person) }
          _button('x',R(People,person),:delete)
        }
      }

      form( :action =&gt; R(People), :method =&gt; 'post') {
        input :name =&gt; 'person[name]'
        input :type =&gt; 'submit', :value =&gt; '+'
      }
    end

    def show_person
      h1 @person.name

      form(:action =&gt; R(People,@person), :method =&gt; :put) {
        input :name =&gt; 'person[name]', :value =&gt; @person.name
        input :type =&gt; 'submit', :value =&gt; 'save'
      }
      a(:href =&gt; R(People)) {"&amp;larr; people"}
    end
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h2&gt;gimme&lt;/h2&gt;


Install with 
&lt;pre&gt;&lt;code class=""&gt;sudo gem install airbed&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;or fetch head from&lt;/p&gt;


&lt;pre&gt;&lt;code class=""&gt;svn co http://rails-oceania.rubyforge.org/svn/airbed/trunk/&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The code is pretty new and shiny, so feedback in eminently welcome. Write some specs if you feel the inclination.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543443" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-08-06:23</id>
    <published>2007-08-06T12:12:00Z</published>
    <updated>2007-08-06T12:12:54Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/8/6/ruby-oo-for-c-devs-part1" rel="alternate" type="text/html" />
    <title>Ruby OO for C developers - part 1 Basic Modeling in OO</title>
<summary type="html">&lt;p&gt;Here’s a post about getting down and dirty with an example of modeling something in both C and Ruby.&lt;/p&gt;


	&lt;p&gt;In C, Object Orientation can be used (somewhat clumsily) as a pattern for modeling and implementing your problem domain. The power of real object oriented languages like Ruby is that this pattern is integrated seamlessly into the language itself.&lt;/p&gt;


	&lt;p&gt;I’m not planning on detailing Ruby syntax itself, but hope that you’ll pick it up in the course of the discussion.&lt;/p&gt;


	&lt;p&gt;For a complete overview of OO concepts, refer to &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming"&gt;Object-oriented programming&lt;/a&gt; at Wikipedia.&lt;/p&gt;


This is the first of a series of articles covering Ruby OO techniques for C developers:
	&lt;ol&gt;
	&lt;li&gt;&lt;a href="http://blog.smartbomb.com.au/2007/8/6/ruby-oo-for-c-devs-part1"&gt;Basic Modeling in OO&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Inheritance&lt;/li&gt;
		&lt;li&gt;Encapsulation&lt;/li&gt;
		&lt;li&gt;Polymorphism&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Anyway. Let’s model!&lt;/p&gt;</summary><content type="html">
            &lt;p&gt;Here’s a post about getting down and dirty with an example of modeling something in both C and Ruby.&lt;/p&gt;


	&lt;p&gt;In C, Object Orientation can be used (somewhat clumsily) as a pattern for modeling and implementing your problem domain. The power of real object oriented languages like Ruby is that this pattern is integrated seamlessly into the language itself.&lt;/p&gt;


	&lt;p&gt;I’m not planning on detailing Ruby syntax itself, but hope that you’ll pick it up in the course of the discussion.&lt;/p&gt;


	&lt;p&gt;For a complete overview of OO concepts, refer to &lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming"&gt;Object-oriented programming&lt;/a&gt; at Wikipedia.&lt;/p&gt;


This is the first of a series of articles covering Ruby OO techniques for C developers:
	&lt;ol&gt;
	&lt;li&gt;&lt;a href="http://blog.smartbomb.com.au/2007/8/6/ruby-oo-for-c-devs-part1"&gt;Basic Modeling in OO&lt;/a&gt;&lt;/li&gt;
		&lt;li&gt;Inheritance&lt;/li&gt;
		&lt;li&gt;Encapsulation&lt;/li&gt;
		&lt;li&gt;Polymorphism&lt;/li&gt;
	&lt;/ol&gt;


	&lt;p&gt;Anyway. Let’s model!&lt;/p&gt;
&lt;h1&gt;Baby steps&lt;/h1&gt;


	&lt;p&gt;We’re going to model TV channels.&lt;/p&gt;


	&lt;p&gt;Our TV channels are viewed using a sophisticated set top box device. From a technical perspective, the box needs a few pieces of information about channels in order to tune to them and show them to the viewer.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;the name of the channel.&lt;/li&gt;
		&lt;li&gt;the channel number.&lt;/li&gt;
		&lt;li&gt;some data to pass to the underlying hardware to tune to the channel.&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;Viewers can tune to a channel by choosing it from a graphical menu.&lt;/p&gt;


	&lt;h2&gt;C&lt;/h2&gt;


	&lt;h3&gt;structure&lt;/h3&gt;


	&lt;p&gt;In C-land, we give form to blobs of memory using structs. A struct defines the shape of a Channel when its allocated in memory.&lt;/p&gt;


&lt;pre&gt;&lt;code class="c"&gt;typedef struct {
  char *name;
  int number
  int tuning_info[3];
} Channel;&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;allocation&lt;/h3&gt;


	&lt;p&gt;To make a real channel from the struct, we allocate it some memory and initialise its information.&lt;/p&gt;


&lt;pre&gt;&lt;code class="c"&gt;Channel *channel_v = (Channel *)malloc(sizeof(Channel));

channel_v-&gt;name = "Channel V";
channel_v-&gt;number = 801;
channel_v-&gt;tuning_info[0] = 4096;
channel_v-&gt;tuning_info[1] = 0;
channel_v-&gt;tuning_info[2] = 123;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;&lt;code&gt;channel_v&lt;/code&gt; is now pointing to an instance of the Channel struct.&lt;/p&gt;


	&lt;p&gt;Note that &lt;code&gt;channel_v&lt;/code&gt; is only known to be shaped like a Channel struct at compile time. Once the code is running, the program has no knowledge of this shape.&lt;/p&gt;


	&lt;p&gt;Using the information stored in an instance is easy:&lt;/p&gt;


&lt;pre&gt;&lt;code class="c"&gt;printf("Channel: %s\n", channel_v-&gt;name);
// output: Channel: Channel V&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;verbs&lt;/h3&gt;


	&lt;p&gt;Now we have our data sorted out, let’s define some functions that do something with instances of the Channel struct.&lt;/p&gt;


&lt;pre&gt;&lt;code class="c"&gt;void channel_tune(Channel *channel) {
  viewer_notify("Tuning to channel %s", channel-&gt;name);
  box_tune_to(channel-&gt;tuning_info[0], channel-&gt;tuning_info[1], channel-&gt;tuning_info[2]);
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;To perform the action “Tune to channel V” :&lt;/p&gt;


&lt;pre&gt;&lt;code class="c"&gt;channel_tune(channel_v);&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;struct verbs&lt;/h3&gt;


	&lt;p&gt;Here’s a function for reading a database file and creating a list of Channel instances:&lt;/p&gt;


&lt;pre&gt;&lt;code class="c"&gt;Channel **channel_load_from_file(char *filename) {
  ...
}&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This function doesn’t take a Channel instance to work on. Instead, it returns a list of Channel instances. 
You could view this function as working with knowledge of the Channel struct in order to produce its Channel instances.&lt;/p&gt;


	&lt;p&gt;Now lets build the same thing in Ruby…&lt;/p&gt;


	&lt;h2&gt;Ruby&lt;/h2&gt;


	&lt;h3&gt;structure&lt;/h3&gt;


	&lt;p&gt;In Ruby-land, classes define the shape of data. In object oriented circles, the shape is called the &lt;strong&gt;interface&lt;/strong&gt;, because the data itself is not directly accessible (later on, we’ll learn that this concept is called &lt;strong&gt;encapsulation&lt;/strong&gt;).&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Channel
  def name
    @name
  end

  def name=(name)
    @name = name
  end

  def number
    @number
  end

  def number=(num)
    @number = num
  end

  def tuning_info
    @tuning_info
  end

  def tuning_info=(tuning_info)
    @tuning_info = tuning_info
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Yuk, that’s a heap of code to do not much at all. It does expose a pile of Ruby concepts to dig through.&lt;/p&gt;


	&lt;p&gt;First of all, functions associated with a class are known as methods. They are like functions which automatically work on instances of the class, or the class itself.&lt;/p&gt;


	&lt;p&gt;The methods defined above are called &lt;strong&gt;instance methods&lt;/strong&gt;, as they only work on instances of Channel.&lt;/p&gt;


	&lt;p&gt;These methods are called accessors—getters and setters—because all they do is get and set the data inside an instance.&lt;/p&gt;


	&lt;p&gt;You may have heard that one of Ruby’s principles is “don’t repeat yourself” (or &lt;span class="caps"&gt;DRY&lt;/span&gt;). Luckily, we can rewrite all this repetitive code much more succinctly:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Channel
  attr_accessor :name, :number, :tuning_info
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;allocation&lt;/h3&gt;


	&lt;p&gt;Channel objects are allocated (or &lt;strong&gt;instantiated&lt;/strong&gt;) using the new method of the Channel class.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;channel_v = Channel.new

channel_v.name        = "Channel V" 
channel_v.number      = 801
channel_v.tuning_info = [4096,0,123]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;At this point the &lt;code&gt;channel_v&lt;/code&gt; variable holds a Channel object. It retains complete knowledge of its structure and place in the hierarchy:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;channel_v.class # =&gt; Channel
channel_v.instance_variables # =&gt; ["@number", "@name", "@tuning_info"]&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This rich reflection information is very useful in many advanced techniques, collectively known as metaprogramming.&lt;/p&gt;


	&lt;h3&gt;verbs&lt;/h3&gt;


	&lt;p&gt;Guess what we use to get things done with Objects and Classes? Yes, right, methods.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Channel
  attr_accessor :name, :number, :tuning_info

  def tune
    Viewer.notify("Tuning to channel #{@name}")
    Box.tune_to(self.tuning_info)
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;To tune to Channel V, we call the tune method on the channel_v instance:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;channel_v.tune&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;an aside on variables&lt;/h3&gt;


	&lt;p&gt;Since we’ve seen a little bit of Ruby code by now, you might have noticed some odd things about the variables.
Ruby has a few different kinds of variables and uses a couple of sigils to differentiate their type.&lt;/p&gt;


	&lt;h4&gt;local variables&lt;/h4&gt;


	&lt;p&gt;Local variables are only visible within the current scope, and any subscopes. They are written as &lt;strong&gt;variable&lt;/strong&gt; (i.e. lower case with underscores)&lt;/p&gt;


	&lt;p&gt;Note that while and for loops don’t introduce new scope in Ruby! Blocks do.&lt;/p&gt;


	&lt;h4&gt;instance variables&lt;/h4&gt;


	&lt;p&gt;Instance variables are variables associated with an instance of a class. They’re visible anywhere within the instance, but not from the outside. They’re somewhat analogous to struct members, except for the encapsulation aspect (don’t worry, we’ll talk about it…).&lt;/p&gt;


	&lt;p&gt;They are written &lt;strong&gt;@variable&lt;/strong&gt; (i.e. like a local variable preceded by an ‘at’).&lt;/p&gt;


	&lt;h4&gt;others&lt;/h4&gt;


	&lt;p&gt;Constants are visible within the current module scope and are written as &lt;strong&gt;Constant&lt;/strong&gt; or &lt;strong&gt;&lt;span class="caps"&gt;CONSTANT&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;Globals are visible anywhere within the current ruby interpreter, and are written as &lt;strong&gt;$global&lt;/strong&gt;&lt;/p&gt;


	&lt;h4&gt;self&lt;/h4&gt;


	&lt;p&gt;Did you notice the use of the word &lt;code&gt;self&lt;/code&gt; in the example above? &lt;code&gt;self&lt;/code&gt; is a special built in variable which refers to the instance for which the method is defined (In this case it wasn’t strictly required, however sometimes its necessary for disambiguation or to take advantage of encapsulation).&lt;/p&gt;


	&lt;h3&gt;class verbs&lt;/h3&gt;


	&lt;p&gt;Methods which act on the class rather than instances of the class are called class methods (or singleton methods). In the method &lt;code&gt;Channel#tune&lt;/code&gt; above, &lt;code&gt;Viewer.notify&lt;/code&gt; and &lt;code&gt;Box.tune_to&lt;/code&gt; are singleton methods.&lt;/p&gt;


	&lt;p&gt;Let’s define a class method for Channel which reads records from a text file and returns a list of Channel objects.&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;class Channel
  def self.load_from_file(file)
    ...
  end
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;The class method is called directly on the class:&lt;/p&gt;


&lt;pre&gt;&lt;code class="ruby"&gt;channels = Channel.load_from_file("channels.txt")&lt;/code&gt;&lt;/pre&gt;

	&lt;h1&gt;Bye till next time&lt;/h1&gt;


	&lt;p&gt;Up to this point there’s not much difference between the structure of the C and Ruby versions.&lt;/p&gt;


	&lt;p&gt;In the next post, I’ll take OO modeling to the next logical step of inheritance. The true utility of OO will become much clearer.&lt;/p&gt;


	&lt;p&gt;I hope you’ve found the journey interesting so far—feedback is always welcome.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543444" height="1" width="1"/&gt;</content>  </entry>
  <entry xml:base="http://blog.smartbomb.com.au/">
    <author>
      <name>lachie</name>
    </author>
    <id>tag:blog.smartbomb.com.au,2007-08-02:19</id>
    <published>2007-08-02T13:32:00Z</published>
    <updated>2007-08-02T13:41:10Z</updated>
    <link href="http://blog.smartbomb.com.au/2007/8/2/roro-on-the-boil" rel="alternate" type="text/html" />
    <title>RORO on the boil</title>
<content type="html">
            &lt;p&gt;There’s a great vibe in Oceania at the moment, especially if you’re a rails developer.&lt;/p&gt;


	&lt;h1&gt;Inaugural intrameetup drinkies&lt;/h1&gt;


	&lt;p&gt;Sydney folk gathered on the roof of the Glenmore Hotel, drank beer and shot the breeze. We pondered what the future holds with passionate developers looking for work often from risk averse businesses.&lt;/p&gt;


	&lt;h1&gt;the first video from Sydney Rails July Meetup&lt;/h1&gt;


	&lt;p&gt;Matt Allen talked about the site he works for, http://iseekgolf.com. Its a good example of a fairly large Rails site.&lt;/p&gt;


&amp;lt;object id="viddler" height="370" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="437"&gt;&amp;lt;param name="movie" value="http://www.viddler.com/player/7a86d99c/" /&gt;&amp;lt;param name="allowScriptAccess" value="always" /&gt;&amp;lt;param name="allowFullScreen" value="true" /&gt;&amp;lt;embed name="viddler" allowfullscreen="true" type="application/x-shockwave-flash" src="http://www.viddler.com/player/7a86d99c/" allowscriptaccess="always" height="370" width="437"&gt;&amp;lt;/embed&gt;&amp;lt;/object&gt;

	&lt;p&gt;&lt;a href="http://toolmantim.com"&gt;Tim&lt;/a&gt; recorded the screencast, while &lt;a href="http://codespike.com"&gt;Jason&lt;/a&gt; was sound man. I post produced it, with wicked tuneage from &lt;a href="http://teamaskins.com"&gt;Ben&lt;/a&gt;. The biggest thing I learned is that editing this stuff sucks without the right tools. Also, the right tools don’t exist yet.&lt;/p&gt;


	&lt;p&gt;My cocoa hat is coming off the shelf tomorrow.&lt;/p&gt;


	&lt;h1&gt;The roro site reskin happened (!)&lt;/h1&gt;


	&lt;p&gt;&lt;a href="http://rubyonrails.com.au"&gt;http://rubyonrails.com.au&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Thanks to everyone who put in the elbow grease, it looks tops.&lt;/p&gt;
          &lt;img src="http://feeds.feedburner.com/~r/Smartbomb/~4/227543445" height="1" width="1"/&gt;</content>  </entry>
</feed>
