<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en-US">
  <title>Rails in the Country - Home</title>
  <id>tag:blog.allen.com.au,2009:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.7.2">Mephisto Noh-Varr</generator>
  
  <link href="http://blog.allen.com.au/" rel="alternate" type="text/html" />
  <updated>2009-03-25T04:28:40Z</updated>
  <link rel="self" href="http://feeds.feedburner.com/RailsInTheCountry" type="application/atom+xml" /><entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2009-03-24:42</id>
    <published>2009-03-24T02:58:00Z</published>
    <updated>2009-03-25T04:28:40Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/yng6XI6hhO0/prangz-com" rel="alternate" type="text/html" />
    <title>Prangz.com</title>
<content type="html">
            &lt;p&gt;Yes, another Friday night coding spree.&lt;/p&gt;


	&lt;p&gt;I was itching to write an app that used real-time, location specific data and so &lt;a href="http://prangz.com"&gt;http://prangz.com&lt;/a&gt; was born.&lt;/p&gt;


	&lt;p&gt;The whole app is 43 lines of code. It’s rails 2.3 and the scraper checks the &lt;span class="caps"&gt;RTA&lt;/span&gt; website every 2 minutes for new data.&lt;/p&gt;


	&lt;p&gt;Next up is an iPhone app, using the new 3.0 push capabilities.  Apply some rules to the firehose so people only get what they want in the way of location and time.  “Send me incidents between home and work after lunch” would be a common use I reckon.&lt;/p&gt;


	&lt;p&gt;I’ve emailed the &lt;span class="caps"&gt;RTA&lt;/span&gt; to alert them to it, let’s see how long I last.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2009/3/24/prangz-com</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2008-07-27:40</id>
    <published>2008-07-27T00:41:00Z</published>
    <updated>2008-07-27T00:45:28Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/j7b23tW52vk/tweetbeer-com-directors-cut" rel="alternate" type="text/html" />
    <title>Tweetbeer.com - Directors Cut</title>
<content type="html">
            &lt;h3&gt;Opening Credits&lt;/h3&gt;


	&lt;p&gt;Here we see Matta doing the dishes on the night of Friday the 25th of July, 2008. As the music is streaming he pauses. He just thought up tweetbeer.com. He goes straight into the living room to IM &lt;a href="http://smartbomb.com.au"&gt;Lachie&lt;/a&gt;, and so it began.&lt;/p&gt;


	&lt;h3&gt;tweetbeer.com&lt;/h3&gt;


	&lt;p&gt;At around 12 midnight of last night Lachie Cox and I launched a fun little app we wrote over the previous day, &lt;a href="http://tweetbeer.com"&gt;tweetbeer.com&lt;/a&gt;. Here’s some little tidbits of info&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;Rails 2.1&lt;/li&gt;
		&lt;li&gt;Mysql DB&lt;/li&gt;
		&lt;li&gt;Haml for layout&lt;/li&gt;
		&lt;li&gt;97 Lines of code&lt;/li&gt;
		&lt;li&gt;Approx 6 hours of dev time&lt;/li&gt;
		&lt;li&gt;git was used as our collabaration tool, worked &lt;strong&gt;so&lt;/strong&gt; well&lt;/li&gt;
		&lt;li&gt;All frontend &lt;span class="caps"&gt;CSS&lt;/span&gt; and the funky-ass logo done by Lachie&lt;/li&gt;
		&lt;li&gt;Tweet parser uses search.twitter.com called via a cron every minute and run through script/runner&lt;/li&gt;
	&lt;/ul&gt;


	&lt;p&gt;So from idea to launch look about 18 hours of real time with about 6 hours of actual coding. Simple ideas are fun. If you could come up with a compelling way to monetize a simple idea like this, that’d be even cooler.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2008/7/27/tweetbeer-com-directors-cut</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2008-06-24:37</id>
    <published>2008-06-24T22:53:00Z</published>
    <updated>2008-06-25T13:30:10Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/hAQX3iGsy-I/rails-camp-the-third" rel="alternate" type="text/html" />
    <title>Rails Camp, the Third</title>
<content type="html">
            &lt;p&gt;Here we are, a few days after the &lt;a href="http://railscamp08.org/"&gt;Third Rails Camp&lt;/a&gt; in Australia.&lt;/p&gt;


	&lt;p&gt;This was my first true rails camp, I attended a day of the first one but due to having a 2 week old baby 4 days/ 3 nights was out of the question. When the 2nd one in Melbourne was on, I was in Fiji with my family, I can’t complain too loudly.&lt;/p&gt;


	&lt;p&gt;Rails Camp was just awesome. The vibe was electric. It was great putting names to faces with the guys from the #roro &lt;span class="caps"&gt;IRC&lt;/span&gt; channel that I spend alot of time in. We asked people to blog about Rails Camp so we could get the word out, here is what I hacked on:&lt;/p&gt;


	&lt;h2&gt;Twetter&lt;/h2&gt;


	&lt;p&gt;Whilst shivering my arse off in bed on Friday night it hit me – how hard would it be to make tiwtter.com resolve to my laptop and watch the logs for the URLs? The answer was, not hard at all. So first thing on Saturday morning I had twitteriffic running locally. It took 50 lines of code in a rails 2.1 app. &lt;a href="http://blog.smartbomb.com.au/"&gt;Lachie&lt;/a&gt; had an example of the &lt;span class="caps"&gt;XML&lt;/span&gt; that the &lt;span class="caps"&gt;API&lt;/span&gt; returned and with a little help from Max M and his internet enabled CrackBerry we were able to read the twitter &lt;span class="caps"&gt;API&lt;/span&gt; docs and get the other bits and pieces. Once &lt;a href="http://lstoll.net/"&gt;Lincoln&lt;/a&gt; woke up I had twitter.com resolving to a shiny new VM on Bigguns (the awesome server) and twitter was alive! There was no friending, everyone got the same stream. I did implement replies but left out direct messages. I think it was a hit.&lt;/p&gt;


	&lt;h2&gt;Merb Caching&lt;/h2&gt;


	&lt;p&gt;I met &lt;a href="http://hassox.blogspot.com/" title="hassox"&gt;Dan Neighman&lt;/a&gt; for the first time in real life. We speak alot on &lt;span class="caps"&gt;IRC&lt;/span&gt; and hang our in #geekdads. He was working on a new caching mechanism for Merb and came to seek me out as the resident Caching Guru. I was flattered.  We spent a good few hours over the weekend fleshing out the solutions to problems that I currently have solved in rails in a hacky, need to use cron kind of way. The outcome was &lt;a href="http://wiki.merbivore.com/pages/background-tasks"&gt;background-tasks&lt;/a&gt;. Dan wrote it up &lt;a href="http://merbunity.com/news/28"&gt;here&lt;/a&gt;. This is Uber exciting and I really want to start Merb Hacking.&lt;/p&gt;


	&lt;h3&gt;Managing Expectations&lt;/h3&gt;


	&lt;p&gt;I decided to give a talk on Managing Expectations. In a previous life this was what our software did but in reality we all have to do it each day. I pegged it as a discussion rather than a talk and that was exactly how it panned out. I reckon there might have been 20 guys all sitting around relating stories about their experiences and how they dealt with them.  I think it’s safe to say that the conclusion was, politics aside, that being open and transparent is the safest way forward, especially if you’re a one-man-band or a small shop.  Clients/Bosses are generally more willing to co-operate if you play it straight.  The talk was actually interrupted by lunch but quite a large proportion actually kept talking whilst eating. I think this was a great outcome for a non-tech talk at a very geeky weekend.&lt;/p&gt;


	&lt;p&gt;So, to all you guys that read this and went, blog it up people! Get it out there. Let’s start a * Camp movement.&lt;/p&gt;


	&lt;p&gt;—Matta&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2008/6/24/rails-camp-the-third</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2008-05-05:32</id>
    <published>2008-05-05T21:49:00Z</published>
    <updated>2008-05-05T21:50:22Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/ewRtYdHw1YA/going-dark-again" rel="alternate" type="text/html" />
    <title>Going Dark. Again</title>
<content type="html">
            &lt;p&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: &lt;a href="http://30sleeps.com/blog/2008/01/31/dealing-with-information-overload/"&gt;I reckon this article has nailed it&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;This weekend was the Anzac weekend, a time for reflection and remembering the things our Grand Fathers and Great Grand Fathers (and possibly Mothers) did for us and our way of life. I miss you Pa.&lt;/p&gt;


	&lt;p&gt;I had the opportunity on Friday night to sit down with some code, uninterrupted. No internet, therefore no Email, IM, &lt;span class="caps"&gt;IRC&lt;/span&gt;, Twitter, &lt;span class="caps"&gt;RSS&lt;/span&gt;. It was &lt;strong&gt;grand&lt;/strong&gt;.&lt;/p&gt;


	&lt;p&gt;It started me thinking, how the hell can us “knowledge” (I hate that term) workers balance being as productive as you know you can with keeping in touch?  The vast majority of my friends are online most of the time, at work, at home and even in between sometimes (Hi Lachlan!). I like being in the loop, I like knowing what’s going on. Twitter has made that a process alot easier than it was 12 months ago.&lt;/p&gt;


	&lt;p&gt;So I have decided that my work day is now going to consist mostly of “off-line” time. 9 – Lunch will be offline, that is, working without distractions. No Email, &lt;span class="caps"&gt;IRC&lt;/span&gt;, IM, Twitter. At Lunch time i’ll surface again for a little while, probably an hour tops. After lunch i’ll hook back in.  After the kids are in bed I may come back on, maybe not. Dunno yet.&lt;/p&gt;


	&lt;p&gt;I tend to embrace things half-heartedly, this is one thing i’m going to try and stick to. If you need me urgently, &lt;span class="caps"&gt;SMS&lt;/span&gt; or Phone is where it’s at.&lt;/p&gt;


	&lt;p&gt;The other side effect I hope this will address is my new level of bored-ness with the interwebs, seriously, I can’t find anything interesting out there atm.&lt;/p&gt;


	&lt;p&gt;Apologies for the above brain dump, upon re-reading it wasn’t very well thought out. Oh Well.&lt;/p&gt;


	&lt;p&gt;Matta&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2008/5/5/going-dark-again</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-12-17:31</id>
    <published>2007-12-17T22:21:00Z</published>
    <updated>2008-03-30T22:05:39Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/XTQNvGwurNU/fluid-app" rel="alternate" type="text/html" />
    <title>Fluid.app</title>
<content type="html">
            &lt;p&gt;Have been using &lt;a href="http://fluidapp.com"&gt;Fluid&lt;/a&gt; for the past week.&lt;/p&gt;


	&lt;p&gt;It’s an &lt;span class="caps"&gt;OS X&lt;/span&gt; (Leopard only) app that lets you create standalone cocoa based web apps, basically a wrapper for web kit.&lt;/p&gt;


	&lt;p&gt;I’ve got one for gmail and unfuddle setup. It’s nice to have them survive browser crashes normally due to unruley javascript.&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://blog.allen.com.au/assets/2007/12/17/Picture_49.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://blog.allen.com.au/assets/2007/12/17/Picture_50.png" alt="" /&gt;&lt;/p&gt;


	&lt;p&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: Here’s a sexy big icon the UF guys sent me&lt;/p&gt;


	&lt;p&gt;&lt;img src="http://blog.allen.com.au/assets/2008/3/30/widget.icon.128.png" alt="" /&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/12/17/fluid-app</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-12-06:28</id>
    <published>2007-12-06T08:23:00Z</published>
    <updated>2007-12-22T20:34:13Z</updated>
    <category term="Rails" />
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/o2OQqlbNeGc/highly-resposive-unfuddlers" rel="alternate" type="text/html" />
    <title>Highly resposive Unfuddlers</title>
<content type="html">
            &lt;p&gt;To follow on from my last post, I have spent the day to-ing and fro-ing with the Unfuddle.com guys and I have come up with an &lt;span class="caps"&gt;SVN&lt;/span&gt; hook for non-UF-hosted svn repos.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://unfuddle.com/community/forums/6/topics/105"&gt;Here’s for code for anyone interested&lt;/a&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/12/6/highly-resposive-unfuddlers</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-11-30:27</id>
    <published>2007-11-30T02:19:00Z</published>
    <updated>2007-12-22T20:34:03Z</updated>
    <category term="Rails" />
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/PsVgUin-j3c/move-over-lighthouse-unfuddle-it-is" rel="alternate" type="text/html" />
    <title>Move over lighthouse, Unfuddle it is</title>
<content type="html">
            &lt;p&gt;So, I blogged earlier about Lighthouse and how much I was in love it with. It has all the features I like but unfortunately for me, it missed a few critical ones my Boss wanted.&lt;/p&gt;


	&lt;p&gt;Enter &lt;a href="http://unfuddle.com/home"&gt;Unfuddle&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;We’ve been using this for a few months now and it works a charm. It’s a rails app and is run buy some very passionate dudes in Hawaii.&lt;/p&gt;


	&lt;p&gt;The feature that really stands out for us is the work flow for tickets. See image below.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://blog.allen.com.au/assets/2007/11/30/Picture_47.png"&gt;&lt;img src="http://blog.allen.com.au/assets/2007/11/30/Picture_47_thumb_1.png" /&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;Boss opens it, I accept it, I resolve it, boss closes it.&lt;/p&gt;


	&lt;p&gt;Boss can reopen it if need be. So easy for me to see what tickets are left to work on in this release, also what tickets need to be verified by him before I can push the release live.&lt;/p&gt;


	&lt;p&gt;Anyone who is dealing with a large ongoing site needs a decent bug tracker, this one is up there with the best i’ve used, both &lt;span class="caps"&gt;OSS&lt;/span&gt; and commercial.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/11/30/move-over-lighthouse-unfuddle-it-is</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-11-27:26</id>
    <published>2007-11-27T01:55:00Z</published>
    <updated>2007-12-15T02:39:52Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/_94qPo6S3tA/print-this-out-give-it-to-your-boss" rel="alternate" type="text/html" />
    <title>Print this out, give it to your boss</title>
<content type="html">
            &lt;p&gt;I don’t actually have to, he sent me the link.&lt;/p&gt;


	&lt;p&gt;This made me a very happy programmer.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://blog.eod.com/post/18462877"&gt;Wide vs. Deep&lt;/a&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/11/27/print-this-out-give-it-to-your-boss</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-10-17:23</id>
    <published>2007-10-17T01:25:00Z</published>
    <updated>2007-10-17T01:25:37Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/ThQclD79nwM/going-dark" rel="alternate" type="text/html" />
    <title>Going Dark</title>
<content type="html">
            &lt;p&gt;Not sure if it’s just me, but lately the constant barrage of IM/IRC/Twitter/Email has been making me feel less productive than I know I can be so for the majority of the day I have been Going Dark. That is, turn comms off and the music up.&lt;/p&gt;


	&lt;p&gt;I don’t go completely off net as I need &lt;a href="http://google.com.au"&gt;my other brain&lt;/a&gt; to remind me of things I constantly forget.&lt;/p&gt;


	&lt;p&gt;I miss my &lt;span class="caps"&gt;IRC&lt;/span&gt; buddies from #roro on freenode.net heaps, they are a constant source of knowledge and entertainment but they are pretty good at posting to the &lt;a href="http://roro.tumblr.com/"&gt;roro tumblr&lt;/a&gt;, so that keeps me in the loop mostly.&lt;/p&gt;


	&lt;p&gt;I actually jump on IM and &lt;span class="caps"&gt;IRC&lt;/span&gt; once or twice during the day, mostly at lunch, or in a lull between pushing out code.&lt;/p&gt;


	&lt;p&gt;I’d like to hear how everyone else deals with the “always on” side of things?&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/10/17/going-dark</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-10-15:22</id>
    <published>2007-10-15T06:34:00Z</published>
    <updated>2007-10-15T06:35:22Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/YWY_dgDqDw0/when-testing-caching" rel="alternate" type="text/html" />
    <title>When Testing Caching ...</title>
<content type="html">
            &lt;p&gt;Don’t forget to set:&lt;/p&gt;


	&lt;p&gt;config.action_controller.perform_caching = true&lt;/p&gt;


	&lt;p&gt;in test.rb in environments. You’ll wonder why nothing is working until you do.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/10/15/when-testing-caching</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-09-17:21</id>
    <published>2007-09-17T11:21:00Z</published>
    <updated>2007-09-17T11:23:05Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/gz70bnn1z5s/33-702635-151-099434-hornsby" rel="alternate" type="text/html" />
    <title>-33.702635,151.099434 : Hornsby</title>
<content type="html">
            &lt;p&gt;So what does a north western Sydney suburb have to do with rails? Not very much, but it has lent it’s name to a very very cool app written by &lt;a href="http://smartbomb.com.au"&gt;Lachie Cox&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;The main aim of &lt;a href="http://rails-oceania.googlecode.com/svn/lachiecox/hornsby/"&gt;Hornsby&lt;/a&gt; is to get rid of the dreaded rails fixtures. As a newcomer to Rails about a year ago, testing was a new and exciting thing for me.  It took a bit of discipline but I got into it. Then I got out of it. Fixtures where p*ssing me off, badly. They were a nightmare to maintain and actually made me write worse code than normal due to the fact I didn’t want to rewrite all my fixtures.&lt;/p&gt;


	&lt;p&gt;I then started using Rspec, I love writing specs but fixtures were still making me swear at my &lt;span class="caps"&gt;MBP&lt;/span&gt;.&lt;/p&gt;


	&lt;p&gt;Hornsby makes me an extremely happy Rails programmer. Here is &lt;a href="http://blog.smartbomb.com.au/2007/8/29/hornsby"&gt;Lachie’s description&lt;/a&gt;.&lt;/p&gt;


	&lt;p&gt;Here’s my code. It’s an example of setting up a “scenario” that I used for testing my Equipment&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;scenario &lt;span class="sy"&gt;:equipment&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@manufacturer&lt;/span&gt; = &lt;span class="co"&gt;EquipmentManufacturer&lt;/span&gt;.create!(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Ben Hogan&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@category&lt;/span&gt; = &lt;span class="co"&gt;EquipmentCategory&lt;/span&gt;.create!(&lt;span class="sy"&gt;:title&lt;/span&gt; =&amp;gt;&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Fairway Woods&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@equipment&lt;/span&gt; = &lt;span class="co"&gt;EquipmentProduct&lt;/span&gt;.new(&lt;span class="sy"&gt;:name&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Edge CFT Ti  Hybrid&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;,&lt;span class="sy"&gt;:equipment_manufacturer_id&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@manufacturer&lt;/span&gt;.id,&lt;span class="sy"&gt;:equipment_category_id&lt;/span&gt; =&amp;gt; &lt;span class="iv"&gt;@category&lt;/span&gt;.id)&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="iv"&gt;@equipment&lt;/span&gt;.save(&lt;span class="pc"&gt;false&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Here is the bit from Rspec test that loads it up.&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;describe &lt;span class="co"&gt;EquipmentController&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  before(&lt;span class="sy"&gt;:each&lt;/span&gt;) &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    hornsby_scenario &lt;span class="sy"&gt;:equipment&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;   ...&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;You’ll notice I hand in “false” to the save method, this allows us to bypass all the validations and setup just the bare minimum to pass tests. This is helpful sometimes but be aware it can lead to other weird stuff than you might need to be aware of, assuming your validations are setup for a reason. Another nice side effect of Hornsby scenarios is the fact that if your DB tables are not the rails default ones you don’t have to jump though hoops to get your Db populated.&lt;/p&gt;


	&lt;p&gt;This software has made my testing life a joy yet again, knowing the exact state of your DB when testing is precisely what was missing from fixtures.&lt;/p&gt;


	&lt;p&gt;Here’s those links again:&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://blog.smartbomb.com.au/2007/8/29/hornsby"&gt;Lachie’s write up&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://rails-oceania.googlecode.com/svn/lachiecox/hornsby/"&gt;Source Code&lt;/a&gt;&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/9/17/33-702635-151-099434-hornsby</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-08-28:12</id>
    <published>2007-08-28T21:56:00Z</published>
    <updated>2007-08-29T07:04:14Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/cTNBOwfj7YQ/out-of-bandwidth-cache-expiry" rel="alternate" type="text/html" />
    <title>Out of Bandwidth Cache Expiry</title>
<content type="html">
            &lt;p&gt;So, you’ve been merrily caching away and using the cache plugin I wrote and you’re still getting some heat about your site sometimes “hanging”. I reckon the problem might be that the person complaining is getting stuck behind a slow running process that is re-caching a page on your site. So what to do?&lt;/p&gt;


	&lt;p&gt;What I’ve done is started an extra mongrel in my pack but not included it in the standard mongrel pack, my (cut down) mongrel config looks like this:&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;--- &lt;tt&gt;
&lt;/tt&gt;port: &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;2222&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;environment: production&lt;tt&gt;
&lt;/tt&gt;address: &lt;span class="fl"&gt;127.0&lt;/span&gt;.&lt;span class="fl"&gt;0.1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;pid_file: log/mongrel.pid&lt;tt&gt;
&lt;/tt&gt;servers: &lt;span class="i"&gt;7&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;As you can see there is 7 mongrels there. Next, setup a second cluster that contains only your 7th mongrel&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&amp;lt;&lt;span class="co"&gt;Proxy&lt;/span&gt; balancer&lt;span class="sy"&gt;:/&lt;/span&gt;/expirecluster&amp;gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;BalancerMember&lt;/span&gt; http&lt;span class="sy"&gt;:/&lt;/span&gt;/&lt;span class="fl"&gt;127.0&lt;/span&gt;.&lt;span class="fl"&gt;0.1&lt;/span&gt;:&lt;span class="i"&gt;2228&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&amp;lt;&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;Proxy&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Next, tell apache to redirect any of your magic expiration URLs to that cluster&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;  &lt;span class="co"&gt;RewriteCond&lt;/span&gt;  &lt;span class="s"&gt;&lt;span class="dl"&gt;%{&lt;/span&gt;&lt;span class="k"&gt;QUERY_STRING&lt;/span&gt;&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt; magic_url_expire_param=&lt;span class="i"&gt;1&lt;/span&gt;&lt;span class="er"&gt;$&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="co"&gt;RewriteRule&lt;/span&gt; ^&lt;span class="rx"&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;span class="k"&gt;(.*)$ balancer:&lt;/span&gt;&lt;span class="dl"&gt;/&lt;/span&gt;&lt;/span&gt;/expirecluster%{&lt;span class="co"&gt;REQUEST_URI&lt;/span&gt;} [&lt;span class="co"&gt;P&lt;/span&gt;,&lt;span class="co"&gt;QSA&lt;/span&gt;,&lt;span class="co"&gt;L&lt;/span&gt;]&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;Restart apache and you’re done. Any cron triggered expire requests will now go through the out of bandwith mongrel and not slow down visitors to you site.&lt;/p&gt;


	&lt;p&gt;This method can actually be used to segregate any URLs off to different clusters, I have a project coming up that will have a lot of slow processes that rely on an external &lt;span class="caps"&gt;SOAP&lt;/span&gt; service running.  They’ll all be farmed off to a cluster running on a totally different machine with trimmed down, DB free mongrels.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/8/28/out-of-bandwidth-cache-expiry</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-08-21:10</id>
    <published>2007-08-21T12:37:00Z</published>
    <updated>2007-08-21T12:53:20Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/iSziNR43Ld4/seesaw-restarting-your-mongrels-with-zero-downtime" rel="alternate" type="text/html" />
    <title>Seesaw, restarting your mongrels with zero downtime</title>
<content type="html">
            &lt;p&gt;Last weekend was the first Sydney Rails Group Hax Day, held by our very own &lt;a href="http://smartbomb.com.au"&gt;Lachie&lt;/a&gt;. What a day! about 10 rails geeks showed up including a few guys we had either never met or only at the previous meet-up.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://synaphy.com"&gt;Max&lt;/a&gt; and I started the day talking about what we’d like to see in a web-based app that managed other rails apps.  In discussing this I mentioned that over that &lt;a href="http://iseekgolf.com"&gt;iseekgolf.com&lt;/a&gt; we’re running getting a serious amount of traffic and a lot of that is e-commerce related, i.e stuff that would really screw me up if the mongrel is was being executed on was killed half way though a process.  This led to me suggesting that it’d be great if you could restart mongrels bit by bit.&lt;/p&gt;


	&lt;p&gt;After about 30 mins of talking it though we decided that the best way was to split the mongrel pack down the middle and bounce each half separately while the other half handled the load. This would potentially slow the site down however it shouldn’t shut the site down entirely.&lt;/p&gt;


	&lt;p&gt;What we came up with was &lt;a href="http://rubyforge.org/frs/shownotes.php?group_id=3286&amp;release_id=13892"&gt;Seesaw&lt;/a&gt;. This does precisely what we needed including configuring the web server on the fly.&lt;/p&gt;


	&lt;p&gt;This morning I installed it live at iseekgolf.com and after a few config tweaks it was working a treat. It brought a huge smile to my face as the logs kept rolling buy as the mongrels were restarting.&lt;/p&gt;


	&lt;p&gt;One gotcha is that by default Seesaw names your mongrel cluster “mongrel_pack”, be sure to replace &lt;strong&gt;all&lt;/strong&gt; instances of your mongrel cluster name in your apache config file to this new name, especially the &lt;span class="caps"&gt;SSL&lt;/span&gt; one ;)&lt;/p&gt;


	&lt;p&gt;Hopefully some people may find a use for this plugin.&lt;/p&gt;


	&lt;p&gt;We’ll be doing some minor changes to it over the coming days, including some definable pauses in between the cluster restarts and apache redirecting traffic to them to give them time to warm up.&lt;/p&gt;


	&lt;p&gt;Max has written up an &lt;a href="http://synaphy.com/2007/8/20/seesaw"&gt;awesome blog entry&lt;/a&gt;, with pretty pictures and all!&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/8/21/seesaw-restarting-your-mongrels-with-zero-downtime</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-08-12:9</id>
    <published>2007-08-12T22:56:00Z</published>
    <updated>2007-08-12T22:56:30Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/P6qlABXCZfg/lighthouse-app-svn-and-you" rel="alternate" type="text/html" />
    <title>Lighthouse App, Svn and you</title>
<content type="html">
            &lt;p&gt;Last week we decided that our ad-hoc issue tracking system wasn’t good enough for the serious development we are doing now.  We tried  Trac, Basecamp and iGTD with email submission. None of them really impressed us for various reasons. Trac was the best of the bunch for bug tracking but never really let us spread our wings.  Basecamp is a great app for what it is meant to do but not the best for bug tracking. I setup iGTD to accept tasks from the boss via email, the problem then was closing the loop, when I was done it was up to me to let the boss know.&lt;/p&gt;


	&lt;p&gt;Enter &lt;a href="http://www.lighthouseapp.com"&gt;Lighthouse&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;What a brilliant piece of software, it’s written by the &lt;a href="http://www.activereload.net/"&gt;Active Reload&lt;/a&gt; guys who also wrote &lt;a href="http://mephistoblog.com/"&gt;Mephisto&lt;/a&gt; the blogging software this blog is written in. The brilliance of this software comes of it’s simplicity. It does the job I want it to do almost perfectly.&lt;/p&gt;


	&lt;p&gt;It doesn’t make any assumptions about things like Bug Priority and such, however it does have a standard tagging system and you can save searches into “bins” that are available on the bug searching screen, we have settled on, low,normal,high,highest and &lt;span class="caps"&gt;URGENT&lt;/span&gt;. See below.&lt;/p&gt;


	&lt;p&gt;&lt;a href="http://blog.allen.com.au/assets/2007/8/12/lighthouse-rgb.jpg"&gt;&lt;img src="http://blog.allen.com.au/assets/2007/8/12/lighthouse-rgb_thumb.jpg"&gt;&lt;/a&gt;&lt;/p&gt;


	&lt;p&gt;I also implemented the &lt;span class="caps"&gt;SVN&lt;/span&gt; integration, the &lt;span class="caps"&gt;FAQ&lt;/span&gt; can be found &lt;a href="http://lighthouseapp.com/help/setting-up-subversion-integration"&gt;here&lt;/a&gt; Now all I do is put a proper comment in the &lt;span class="caps"&gt;SVN&lt;/span&gt; commit that explains the changes and has the lighthouse syntax in it, an example might be “Changes to log form [#15 state:resolved]”. A commit with that comment in it closes the ticket as well, brilliant.&lt;/p&gt;


	&lt;p&gt;So the aim of this post was really just to send props to Rick and the team at Active Reload, it’s great to see an app by the geeks, for the geeks.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/8/12/lighthouse-app-svn-and-you</feedburner:origLink></entry>
  <entry xml:base="http://blog.allen.com.au/">
    <author>
      <name>Matt Allen</name>
    </author>
    <id>tag:blog.allen.com.au,2007-08-10:8</id>
    <published>2007-08-10T08:28:00Z</published>
    <updated>2007-08-10T08:28:35Z</updated>
    <link href="http://feedproxy.google.com/~r/RailsInTheCountry/~3/KeJGS-tiIrM/the-caching-gap-tm-mixin-it-with-cron" rel="alternate" type="text/html" />
    <title>The Caching Gap(tm) ... mixin' it with Cron</title>
<content type="html">
            &lt;p&gt;So the plugin i mentioned in my &lt;a href="http://blog.allen.com.au/2007/8/8/the-caching-gap-tm"&gt;last post&lt;/a&gt; is alive and kicking, it has totally solved the problem we were having.&lt;/p&gt;


	&lt;p&gt;A new problem arose today, now that the pages are begin re-cached as part of the sweeping process, it was taking ages. Ages being up to 60 seconds to re-cache them all, also ages with the boss sitting there waiting for thing to happen. Not so good from a Usability perspective.&lt;/p&gt;


	&lt;p&gt;Again, I was throwing the idea of using &lt;span class="caps"&gt;DRB&lt;/span&gt; around on &lt;span class="caps"&gt;IRC&lt;/span&gt; and &lt;a href="http://smartbomb.com.au/"&gt;Lachie Cox&lt;/a&gt; suggested good old cron. We are already using cron to expire the front page on the hour to keep the info fresh so I thought i’d expand it a little.&lt;/p&gt;


	&lt;p&gt;I created a new model called CacheQueue that had two columns, cache_type and cache_data. The two types of cache I hose now are the regular esxpressions that get handed into an expire_fragment method, or the urls that get the special param handed in and get re-cached up.&lt;/p&gt;


	&lt;p&gt;The sweeper now looks like this&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;## The  Sweeper&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;TournamentSweeper&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Caching&lt;/span&gt;::&lt;span class="co"&gt;Sweeper&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  observe ...models...&lt;tt&gt;
&lt;/tt&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="fu"&gt;after_save&lt;/span&gt;(record)&lt;tt&gt;
&lt;/tt&gt;      ...  &lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;CacheQueue&lt;/span&gt;.create({&lt;span class="sy"&gt;:cache_type&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:cache_data&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;/?special_param_to_hose_cache=1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;})&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;CacheQueue&lt;/span&gt;.create({&lt;span class="sy"&gt;:cache_type&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;regex&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;, &lt;span class="sy"&gt;:cache_data&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;tournaments/&lt;/span&gt;&lt;span class="il"&gt;&lt;span class="dl"&gt;#{&lt;/span&gt;tournament.id&lt;span class="dl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class="k"&gt;-*&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;})&lt;tt&gt;
&lt;/tt&gt;      ...&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;So we’re creating lots of entires in the cache_queues table, all having an expired = 0 column by default.&lt;/p&gt;


	&lt;p&gt;The next step was to write a method that could be called from a rake task that expires the caches, here it is&lt;/p&gt;


&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;7&lt;tt&gt;
&lt;/tt&gt;8&lt;tt&gt;
&lt;/tt&gt;9&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;10&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;11&lt;tt&gt;
&lt;/tt&gt;12&lt;tt&gt;
&lt;/tt&gt;13&lt;tt&gt;
&lt;/tt&gt;14&lt;tt&gt;
&lt;/tt&gt;15&lt;tt&gt;
&lt;/tt&gt;16&lt;tt&gt;
&lt;/tt&gt;17&lt;tt&gt;
&lt;/tt&gt;18&lt;tt&gt;
&lt;/tt&gt;19&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;20&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;21&lt;tt&gt;
&lt;/tt&gt;22&lt;tt&gt;
&lt;/tt&gt;23&lt;tt&gt;
&lt;/tt&gt;24&lt;tt&gt;
&lt;/tt&gt;25&lt;tt&gt;
&lt;/tt&gt;26&lt;tt&gt;
&lt;/tt&gt;27&lt;tt&gt;
&lt;/tt&gt;28&lt;tt&gt;
&lt;/tt&gt;29&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;30&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;31&lt;tt&gt;
&lt;/tt&gt;32&lt;tt&gt;
&lt;/tt&gt;33&lt;tt&gt;
&lt;/tt&gt;34&lt;tt&gt;
&lt;/tt&gt;35&lt;tt&gt;
&lt;/tt&gt;36&lt;tt&gt;
&lt;/tt&gt;37&lt;tt&gt;
&lt;/tt&gt;38&lt;tt&gt;
&lt;/tt&gt;39&lt;tt&gt;
&lt;/tt&gt;&lt;strong&gt;40&lt;/strong&gt;&lt;tt&gt;
&lt;/tt&gt;41&lt;tt&gt;
&lt;/tt&gt;42&lt;tt&gt;
&lt;/tt&gt;43&lt;tt&gt;
&lt;/tt&gt;44&lt;tt&gt;
&lt;/tt&gt;45&lt;tt&gt;
&lt;/tt&gt;46&lt;tt&gt;
&lt;/tt&gt;47&lt;tt&gt;
&lt;/tt&gt;48&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;## The  CacheQueue Class&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;class&lt;/span&gt; &lt;span class="cl"&gt;CacheQueue&lt;/span&gt; &amp;lt; &lt;span class="co"&gt;ActiveRecord&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;def&lt;/span&gt; &lt;span class="pc"&gt;self&lt;/span&gt;.expire&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;begin&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      require &lt;span class="s"&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="k"&gt;action_controller/integration&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="c"&gt;# wite a disc lock&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      lockfile = &lt;span class="co"&gt;RAILS_ROOT&lt;/span&gt; + &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;/log/cache.expire&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;if&lt;/span&gt; &lt;span class="co"&gt;File&lt;/span&gt;.exists? lockfile&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="gv"&gt;$stderr&lt;/span&gt;.puts &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;Locked since &lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; + &lt;span class="co"&gt;File&lt;/span&gt;.open(lockfile,&lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;r&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;).atime.to_s&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;return&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;FileUtils&lt;/span&gt;.touch lockfile&lt;tt&gt;
&lt;/tt&gt;      caches_to_be_hosed = &lt;span class="co"&gt;CacheQueue&lt;/span&gt;.find(&lt;span class="sy"&gt;:all&lt;/span&gt;,&lt;span class="sy"&gt;:conditions&lt;/span&gt; =&amp;gt; {&lt;span class="sy"&gt;:expired&lt;/span&gt; =&amp;gt; &lt;span class="pc"&gt;false&lt;/span&gt;}, &lt;span class="sy"&gt;:order&lt;/span&gt; =&amp;gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;cache_type DESC, id ASC&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;      hosed_url_caches = []&lt;tt&gt;
&lt;/tt&gt;      hosed_regex_caches = []&lt;tt&gt;
&lt;/tt&gt;      sess = &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Integration&lt;/span&gt;::&lt;span class="co"&gt;Session&lt;/span&gt;.new&lt;tt&gt;
&lt;/tt&gt;      sess.host! &lt;span class="co"&gt;LIVE_HOST&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      c = &lt;span class="co"&gt;ActionController&lt;/span&gt;::&lt;span class="co"&gt;Base&lt;/span&gt;.new &lt;tt&gt;
&lt;/tt&gt;      skipped = &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      caches_to_be_hosed.each &lt;span class="r"&gt;do&lt;/span&gt; |cache|&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="c"&gt;# update the db&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        cache.expired = &lt;span class="pc"&gt;true&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;        cache.save!&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;case&lt;/span&gt; cache.cache_type&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            &lt;span class="r"&gt;if&lt;/span&gt; hosed_url_caches.include? cache.cache_data&lt;tt&gt;
&lt;/tt&gt;              skipped += &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;              &lt;span class="r"&gt;next&lt;/span&gt; &lt;tt&gt;
&lt;/tt&gt;            &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            sess.get cache.cache_data&lt;tt&gt;
&lt;/tt&gt;            hosed_url_caches &amp;lt;&amp;lt; cache.cache_data&lt;tt&gt;
&lt;/tt&gt;          &lt;span class="r"&gt;when&lt;/span&gt; &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt;regex&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            &lt;span class="r"&gt;if&lt;/span&gt; hosed_regex_caches.include? cache.cache_data&lt;tt&gt;
&lt;/tt&gt;              skipped += &lt;span class="i"&gt;1&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;              &lt;span class="r"&gt;next&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;            c.expire_fragment(&lt;span class="co"&gt;Regexp&lt;/span&gt;.new(cache.cache_data))&lt;tt&gt;
&lt;/tt&gt;            hosed_regex_caches &amp;lt;&amp;lt; cache.cache_data&lt;tt&gt;
&lt;/tt&gt;        &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;FileUtils&lt;/span&gt;.rm lockfile&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;rescue&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;      &lt;span class="co"&gt;FileUtils&lt;/span&gt;.rm lockfile&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="gv"&gt;$stderr&lt;/span&gt;.puts ((hosed_regex_caches.size + hosed_url_caches.size).to_s + &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt; caches removed&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;) &lt;span class="r"&gt;if&lt;/span&gt; (hosed_regex_caches.size + hosed_url_caches.size &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt;)&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="gv"&gt;$stderr&lt;/span&gt;.puts skipped.to_s + &lt;span class="s"&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;span class="k"&gt; caches skipped&lt;/span&gt;&lt;span class="dl"&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt; &lt;span class="r"&gt;if&lt;/span&gt; skipped &amp;gt; &lt;span class="i"&gt;0&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;

&lt;table class="CodeRay"&gt;&lt;tr&gt;
  &lt;td title="click to toggle" class="line_numbers"&gt;&lt;pre&gt;1&lt;tt&gt;
&lt;/tt&gt;2&lt;tt&gt;
&lt;/tt&gt;3&lt;tt&gt;
&lt;/tt&gt;4&lt;tt&gt;
&lt;/tt&gt;5&lt;tt&gt;
&lt;/tt&gt;6&lt;tt&gt;
&lt;/tt&gt;&lt;/pre&gt;&lt;/td&gt;
  &lt;td class="code"&gt;&lt;pre&gt;&lt;span class="c"&gt;## The  Rake task&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;namespace &lt;span class="sy"&gt;:cache&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;  task &lt;span class="sy"&gt;:expire&lt;/span&gt; =&amp;gt;  &lt;span class="sy"&gt;:environment&lt;/span&gt; &lt;span class="r"&gt;do&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;    &lt;span class="co"&gt;CacheQueue&lt;/span&gt;.expire&lt;tt&gt;
&lt;/tt&gt;  &lt;span class="r"&gt;end&lt;/span&gt;&lt;tt&gt;
&lt;/tt&gt;&lt;span class="r"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;&lt;/table&gt;


	&lt;p&gt;This write out to $stderr, when it actually does something it send me an email. It also implements locking so it doesn’t run over itself.&lt;/p&gt;


	&lt;p&gt;One of the cool parts of this is that it’ll actually skip over a cache if it already hosed it, so if in the space of the 4 minutes when it was run last the boss had edited the same article twice, which would schedule the re-caching of the front page and other busy pages, this method would only do each one once, your machine will thank you.&lt;/p&gt;
          </content>  <feedburner:origLink>http://blog.allen.com.au/2007/8/10/the-caching-gap-tm-mixin-it-with-cron</feedburner:origLink></entry>
</feed>
