<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title></title>
  <link href="http://wholemeal.co.nz/atom.xml" rel="self"/>
  <link href="http://wholemeal.co.nz/"/>
  <updated>2012-04-25T00:09:48+12:00</updated>
  <id>http://wholemeal.co.nz/</id>
  <author>
    <name>Malcolm Locke</name>
    
  </author>

  
  <entry>
    <title>Secure Password Storage With Vim and GnuPG</title>
    <link href="http://wholemeal.co.nz/blog/2012/03/11/secure-password-storage-with-vim-and-gpg/"/>
    <updated>2012-03-11T23:09:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2012/03/11/secure-password-storage-with-vim-and-gpg</id>
    <content type="html">&lt;p&gt;There are a raft of tools out there for secure storage of passwords, but they
will all come and go, Vim and GnuPG are forever.&lt;/p&gt;

&lt;p&gt;Here's the config:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;vim&quot;&gt;augroup encrypted
    au&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;    &amp;quot; First make sure nothing is written to ~/.viminfo while editing&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;    &amp;quot; an encrypted file.&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPre&lt;/span&gt;      *.gpg &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;viminfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;    &amp;quot; We don&amp;#39;t want a swap file, as it writes unencrypted data to disk&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPre&lt;/span&gt;      *.gpg &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;noswapfile&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;    &amp;quot; Switch to binary mode to read the encrypted file&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPre&lt;/span&gt;      *.gpg &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPre&lt;/span&gt;      *.gpg &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; ch_save &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPost&lt;/span&gt;    *.gpg &lt;span class=&quot;s1&quot;&gt;&amp;#39;[,&amp;#39;&lt;/span&gt;]&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;gpg &lt;span class=&quot;p&quot;&gt;--&lt;/span&gt;decrypt &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;sr&quot;&gt;/dev/&lt;/span&gt;null
&lt;span class=&quot;c&quot;&gt;    &amp;quot; Switch to normal mode for editing&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPost&lt;/span&gt;    *.gpg &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;nobin&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPost&lt;/span&gt;    *.gpg &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;ch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; ch_save&lt;span class=&quot;p&quot;&gt;|&lt;/span&gt;unlet ch_save
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPost&lt;/span&gt;    *.gpg execute &lt;span class=&quot;s2&quot;&gt;&amp;quot;:doautocmd BufReadPost &amp;quot;&lt;/span&gt; . expand&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;%:r&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;    &amp;quot; Convert all text to encrypted text before writing&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufWritePre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileWritePre&lt;/span&gt;    *.gpg   &lt;span class=&quot;s1&quot;&gt;&amp;#39;[,&amp;#39;&lt;/span&gt;]&lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;gpg &lt;span class=&quot;p&quot;&gt;--&lt;/span&gt;default&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;recipient&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;self &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;ae &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;sr&quot;&gt;/dev/&lt;/span&gt;null
&lt;span class=&quot;c&quot;&gt;    &amp;quot; Undo the encryption so we are back in the normal text, directly&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;    &amp;quot; after the file has been written.&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufWritePost&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileWritePost&lt;/span&gt;  *.gpg   &lt;span class=&quot;k&quot;&gt;u&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;    &amp;quot; Fold entries by default&lt;/span&gt;
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPre&lt;/span&gt;      *.gpg &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;foldmethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;expr
    autocmd &lt;span class=&quot;nb&quot;&gt;BufReadPre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;FileReadPre&lt;/span&gt;      *.gpg &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;foldexpr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;getline&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;v:lnum&lt;span class=&quot;p&quot;&gt;)=~&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;^\\s*$&amp;#39;&lt;/span&gt;&amp;amp;&amp;amp;getline&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;v:lnum&lt;span class=&quot;p&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)=~&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;\\S&amp;#39;&lt;/span&gt;?&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;1&amp;#39;&lt;/span&gt;:&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;
augroup END
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Now, open a file, say &lt;code&gt;super_secret_passwords.gpg&lt;/code&gt; and enter your passwords
with a blank line between each set:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;My Twitter account
malc : s3cr3t

My Facebook account
malc : s3cr3t

My LinkedIn account
malc : s3cr3t
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When you write the file out, it will be encrypted with your GPG key.  When
you next open it, you'll be prompted for your GPG private key passphrase to
decrypt the file.&lt;/p&gt;

&lt;p&gt;The line folding config will mean all the passwords will be hidden by default
when you open the file, you can reveal the details using &lt;code&gt;zo&lt;/code&gt; (or right arrow /
&lt;code&gt;l&lt;/code&gt;) with the cursor over the password title.&lt;/p&gt;

&lt;p&gt;I like this system because as long as I have &lt;code&gt;gpg&lt;/code&gt; and my private key available,
I can extract any long lost password from my collection.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Building RedCloth With Bundler and GCC 4.6</title>
    <link href="http://wholemeal.co.nz/blog/2011/11/25/building-redcloth-with-bundler-and-gcc-4-6/"/>
    <updated>2011-11-25T15:49:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/11/25/building-redcloth-with-bundler-and-gcc-4-6</id>
    <content type="html">&lt;p&gt;Getting ready to work on a problem in Rails on an Ubuntu Oneiric (11.10)
machine, I ran across the following problem running &lt;code&gt;bundle install&lt;/code&gt; for
Rails core:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;pre&gt;&lt;code&gt;$ bundle install
Updating git://github.com/rails/arel
Updating git://github.com/rails/journey
Fetching source index for http://rubygems.org/
Using rake (0.8.7) 
Installing RedCloth (4.2.7) with native extensions 
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

        /home/malc/.rvm/rubies/ruby-1.9.2-p290/bin/ruby extconf.rb 
checking for main() in -lc... yes
creating Makefile

make
gcc -I. -I/home/malc/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-linux -I/home/malc/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/home/malc/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I.   -fPIC -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long  -fPIC -O0 -Wall -Werror  -o redcloth_scan.o -c redcloth_scan.c
gcc -I. -I/home/malc/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-linux -I/home/malc/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/home/malc/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I.   -fPIC -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long  -fPIC -O0 -Wall -Werror  -o redcloth_inline.o -c redcloth_inline.c
ragel/redcloth_inline.c.rl: In function ‘red_block’:
ragel/redcloth_inline.c.rl:99:9: error: variable ‘attr_regs’ set but not used [-Werror=unused-but-set-variable]
cc1: all warnings being treated as errors

make: *** [redcloth_inline.o] Error 1


Gem files will remain installed in /home/malc/.gem/ruby/1.9.1/gems/RedCloth-4.2.7 for inspection.
Results logged to /home/malc/.gem/ruby/1.9.1/gems/RedCloth-4.2.7/ext/redcloth_scan/gem_make.out
An error occured while installing RedCloth (4.2.7), and Bundler cannot continue.
Make sure that `gem install RedCloth -v '4.2.7'` succeeds before bundling.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;




&lt;!-- more --&gt;


&lt;p&gt;Until this is fixed in RedCloth, you can work around it by specifying extra build
options for &lt;code&gt;bundler&lt;/code&gt; which will only be applied when building RedCloth:&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;pre&gt;&lt;code&gt;$ bundle config build.RedCloth --with-cflags=-w&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;After this &lt;code&gt;bundle install&lt;/code&gt; should work as normal.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Start as You Mean to Go On</title>
    <link href="http://wholemeal.co.nz/blog/2011/11/11/start-as-you-mean-to-go-on/"/>
    <updated>2011-11-11T21:42:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/11/11/start-as-you-mean-to-go-on</id>
    <content type="html">&lt;p&gt;&lt;img class='' src='/images/chch-cycle-path.jpg' width='' height='' alt='' title=''&gt;&lt;/p&gt;

&lt;p&gt;Those who know me know I'm a keen cyclist.  Not in the lycra clad, ultra high
tech, kilometre counting way, but in the cruise to the dairy, 3 speed, lazy
cruiser, ride the kids to school way.&lt;/p&gt;

&lt;p&gt;The short time I spent living in the Netherlands has made me aware of how
Christchurch could be one of the worlds great cycling cities.  Flat as a
pancake, a favourable climate and super wide streets, all the ingredients are
in place.&lt;/p&gt;

&lt;p&gt;But biking in Christchurch is, quite frankly, hellish.  It's mostly a cultural
problem.  The city is built for cars, and bikes and pedestrians are very much
second class citizens.&lt;/p&gt;

&lt;p&gt;But then the earthquakes happened, and the landscape changed, both physically
and in the hearts of the cities people.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;The council ran the
&lt;a href=&quot;http://www.centralcityplan.org.nz/info/share-an-idea.aspx&quot;&gt;share an idea&lt;/a&gt;
initiative to find out what the people wanted to see in the rebuild of the
city.  And common themes started to emerge, a people friendly, green city,
with great public transport, a pedestrian and cycle friendly city.  When the
rebuild began, it looked like we might finally get the city I'd always dreamed
Christchurch could be, a great cycling city.&lt;/p&gt;

&lt;p&gt;But the reality is, the rebuild began the day after the earthquake.  We're not
waiting for it to happen, it's happening now.  I'd love to be positive about
the direction the work has taken so far, but it looks like the same old same
old.&lt;/p&gt;

&lt;p&gt;Below are a few example of ways cycling has been integrated into the major
projects undertaken so far.&lt;/p&gt;

&lt;h2&gt;The Central Bus Station&lt;/h2&gt;

&lt;p&gt;For the past few years, the cities buses have been gradually being fitted with
cycle racks.  This is a great initiative, but it had a small problem.  It was
not possible, for safety reasons due to the layout, to load bikes onto the
buses in the cities central bus exchange.  This is fair enough, the exchange
preceded the bike racks by many years, and it's successor could be designed
without this problem.&lt;/p&gt;

&lt;p&gt;The opportunity came earlier than expected, and a temporary bus station has
been built to take the place of the damaged bus exchange, and is expected to
be in operation for at least 2 years.&lt;/p&gt;

&lt;p&gt;And guess what?  You still cannot load your bike onto bike racks in the new
central station, with lack of space being cited.&lt;/p&gt;

&lt;h2&gt;Re:Start the heart&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6333379237/&quot; title=&quot;RE:Start project, Christchurch, NZ by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6118/6333379237_fa1816ec8a.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;RE:Start project, Christchurch, NZ&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the most exciting projects in the central city is the 'RE:Start' project.
A retail precinct has been constructed using shipping containers in part of
the Cashel Mall, one of the pedestrianised areas in the heart of the city.&lt;/p&gt;

&lt;p&gt;The project has created a really funky space, vibrant space.  Personally, I
feel the space is an order of magnitude better than before the quake.&lt;/p&gt;

&lt;p&gt;But yet again, we have zero provision for cycles in this space.  3 large car
parks have been set up, making access by car incredibly easy.  As &lt;a href=&quot;http://www.rebuildchristchurch.co.nz/blog/2011/11/project-re-start---opinion&quot;&gt;reported elsewhere by James Dann&lt;/a&gt;
it seems to be a glaring ommission for our new, supposedly cycle friendly
CBD.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;... when you remember the focus that the draft city plan put on a &quot;cycle-friendly&lt;br/&gt;city&quot;. This was far from that.&lt;/p&gt;&lt;p&gt;While I realise that the whole mall was put together at very short notice, and&lt;br/&gt;this may just be an oversight, it alarms me that one of the main selling points&lt;br/&gt;of the city plan seems to have already been forgotten.&lt;/p&gt;&lt;/blockquote&gt;


&lt;p&gt;It's not like there isn't a demand, people are locking their bikes to anything
that doesn't move.  I suggest you do the same, make the ommission obvious.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6333386477/&quot; title=&quot;Bike parking in Cashel Mall by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6056/6333386477_4a1353dc87.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Bike parking in Cashel Mall&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6333381637/&quot; title=&quot;Bike parking in Cashel Mall by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6060/6333381637_7c15ffd762.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Bike parking in Cashel Mall&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6334137498/&quot; title=&quot;Bike parking in Cashel Mall by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6101/6334137498_056f82d6ae.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Bike parking in Cashel Mall&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6334136846/&quot; title=&quot;Bike parking in Cashel Mall by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6213/6334136846_d38a49d694.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Bike parking in Cashel Mall&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6333378463/&quot; title=&quot;Bike parking in Cashel Mall by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6106/6333378463_0651cf79e6.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Bike parking in Cashel Mall&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;The Earth From Above Exhibition&lt;/h2&gt;

&lt;p&gt;Off road cycle paths are pretty rare in Christchurch, with painted cycle lanes
on the road more commonplace.  One of the few off road cycle paths that we do
have on Rolleston Avenue was closed for nearly 2 months in August to make way
for &lt;a href=&quot;http://www.celsias.co.nz/article/environmental-art-show-christchurch-just-awesome/&quot;&gt;an art installation about sustainable development.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Can anyone spell irony?&lt;/p&gt;

&lt;h2&gt;The St. Asaph Street cycle way&lt;/h2&gt;

&lt;p&gt;I'm not really a fan of the kind article that I've just written.  I much prefer
a positive angle.  So I thought I'd better write up all the pro-cycling work
that has been carried out for balance.&lt;/p&gt;

&lt;p&gt;This is really the only thing I can find.  A bike lane has been set up on
St Asaph Street, shared with pedestrians.  This is great.  It represents one
of the only east-west routes accross the CBD, and it's great that a little
common sense has been applied to give cyclists a physically seperate path on
this road.  It's low tech, but given the circumstances, I'll take it.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6334143168/&quot; title=&quot;Temporary Bike Lane on St Asaph Street by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6094/6334143168_4e35aae6f1.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Temporary Bike Lane on St Asaph Street&quot;&gt;&lt;/a&gt;
&lt;a href=&quot;http://www.flickr.com/photos/malclocke/6334142392/&quot; title=&quot;Temporary Bike Lane on St Asaph Street by malclocke, on Flickr&quot;&gt;&lt;img src=&quot;http://farm7.static.flickr.com/6225/6334142392_16e837a971.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;Temporary Bike Lane on St Asaph Street&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yet, the fact that this is really the best and only piece of bike friendly
work I can find in the whole city is fairly sad.  If there are other, better
projects that have taken place please let me know and I'll add them.&lt;/p&gt;

&lt;p&gt;In conclusion, I'm afraid I'm not very hopefull that the city is going to
be transferred into the cycling utopia it could so easily be.  Please, City
Council, prove me wrong.  Please.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The Mystery of Tuenti Mobile for Android</title>
    <link href="http://wholemeal.co.nz/blog/2011/10/10/the-mystery-of-tuenti-mobile-for-android/"/>
    <updated>2011-10-10T20:07:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/10/10/the-mystery-of-tuenti-mobile-for-android</id>
    <content type="html">&lt;p&gt;&lt;img class='' src='/images/tuenti.png' width='' height='' alt='' title=''&gt;&lt;/p&gt;

&lt;p&gt;I'm not quite sure what to make of this, and google is so far not throwing
anything up for me.  I've put this post up to see if anyone else who's seeing
the same thing as me could leave some comments to shed some light on the
subject.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;A few days ago, I noticed that application 'Tuenti Mobile' was appearing in the
upgrade list in the Android Market on my phone (low spec Huawei U8210 on
Vodafone NZ, branded as a Vodafone 845, Android 2.1).  Now, this is strange in
several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I never installed this app&lt;/li&gt;
&lt;li&gt;The application appears to be for a Spanish social network&lt;/li&gt;
&lt;li&gt;There is no 'uninstall' option for the app.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The application &lt;a href=&quot;https://market.android.com/details?id=com.tuenti.android.client&amp;amp;hl=en&quot;&gt;appears to be valid&lt;/a&gt;,
and before a couple of days ago it was showing nothing but positive comments on
the Android Market, with over 250,000 downloads.&lt;/p&gt;

&lt;p&gt;However, looking back at it today, it appears I'm not the only person in the
dark as to how and why this app has ended up on their device:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;to delete this ap u have to go to privacy settings an reset yr,fone. ~ Susan&lt;/p&gt;

&lt;p&gt;I dont understand his and i cant uninstall it.help please? ~ Edona&lt;/p&gt;

&lt;p&gt;What the hell why cant i delete it?? D: ~ Michael&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;The fact that there is no uninstall option is very strange, as if the app is
part of the ROM on my phone.  But it doesn't appear in the list of applications
on the phone, only on the Market update list.&lt;/p&gt;

&lt;p&gt;Curiouser and curiouser ... leave a comment with details of your device if you're
having the same problem.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;strong&gt;UPDATE:&lt;/strong&gt; After further investigation, it doesn't look like there is anything
sinister about this app.  It appears to be part of the default
&lt;a href=&quot;http://en.wikipedia.org/wiki/Pre-installed_software&quot;&gt;crapware&lt;/a&gt; installed on
the ROM from Vodafone, i.e. the default set of software that Vodafone installs
when shipping a device.&lt;/p&gt;

&lt;p&gt;There is &lt;a href=&quot;http://www.telecompaper.com/news/vodafone-spain-deploys-tuenti-app-on-mobile-phones&quot;&gt;evidence&lt;/a&gt;
scattered around the net that there is probably a &lt;a href=&quot;http://blog.vodafone.com.au/blog/tuenti-an-exclusive-network-in-spain/&quot;&gt;commercial relationship&lt;/a&gt;
between Vodafone and Tuenti.  If you're having the same problem, I'm betting
you have a Vodafone branded phone too.&lt;/p&gt;

&lt;p&gt;For now, it looks like I may have to put up with this upgrade lingering in
the list on the Android Market, but at least it doesn't look like anything
malicious is going on.  If I work out a way of removing the app I'll update
this post.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Chrome vs Firefox Javascript Date Differences</title>
    <link href="http://wholemeal.co.nz/blog/2011/09/09/chrome-firefox-javascript-date-differences/"/>
    <updated>2011-09-09T21:33:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/09/09/chrome-firefox-javascript-date-differences</id>
    <content type="html">&lt;p&gt;Spent a fair amount of time wracking my brain over a problem caused by this
today.  It turns out there are some subtle implementation differences between
Firefox and Chrome when parsing date strings:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Chrome&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;2011-10-31&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Sun Oct 30 2011 00:00:00 GMT+1300 (NZDT)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Firefox&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;2011-10-31&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Sun Oct 30 2011 13:00:00 GMT+1300 (NZST)&lt;/span&gt;
                        &lt;span class=&quot;c1&quot;&gt;//                 ^^^^^^^^&lt;/span&gt;
                        &lt;span class=&quot;c1&quot;&gt;//                 Different default hour&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;When parsing a date as a string without an explicit time, Chrome will default
the &lt;code&gt;Date&lt;/code&gt; object's time to midnight &lt;em&gt;local time&lt;/em&gt;.  Firefox will default it to
midnight &lt;em&gt;GMT&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;To ensure the same behaviour across both browsers, use the following
style of initialiser.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;javascript&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Note that the month numbers are zero indexed, so Jan is 0, Dec 11.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Year and day numbers are *not* zero indexed.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Date&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2011&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Returns Mon Oct 31 2011 00:00:00 GMT+1300 in Chrome and firefox.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>Presenting Backbone.js at Christchurch on Rails</title>
    <link href="http://wholemeal.co.nz/blog/2011/09/07/presenting-backbone-js-at-christchurch-on-rails/"/>
    <updated>2011-09-07T12:18:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/09/07/presenting-backbone-js-at-christchurch-on-rails</id>
    <content type="html">&lt;p&gt;I'll be giving a short presentation on
&lt;a href=&quot;http://documentcloud.github.com/backbone/&quot;&gt;Backbone.js&lt;/a&gt; at the next
&lt;a href=&quot;http://groups.google.com/group/christchurch-on-rails&quot;&gt;Christchurch on Rails&lt;/a&gt;
meeting.  There's also potentially another short talk on
&lt;a href=&quot;http://jashkenas.github.com/coffee-script/&quot;&gt;CoffeeScript&lt;/a&gt; on the cards,
so it will be a Javascript only night and may be of interest to non Rails
folk.&lt;/p&gt;

&lt;p&gt;Venue is being provided by the lovely folks at &lt;a href=&quot;http://trineo.co.nz/&quot;&gt;Trineo&lt;/a&gt;,
and drinks and nibbles from the equally lovely folks at
&lt;a href=&quot;http://resolvedigital.com/&quot;&gt;Resolve Digital&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Where:&lt;/em&gt; Trineo Ltd, Unit 2C, 105 Gasson St (entrance at rear)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;When:&lt;/em&gt; Thu 15th Sep 2011 - 17:30&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;See you there!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Geeks on Bikes</title>
    <link href="http://wholemeal.co.nz/blog/2011/08/20/geeks-on-bikes/"/>
    <updated>2011-08-20T22:00:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/08/20/geeks-on-bikes</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;NOTE &gt;&gt;&gt;&gt; CANCELLED DUE TO LACK OF INTEREST &amp;lt;&amp;lt;&amp;lt;&amp;lt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strike&gt;
I've been toying with getting this going for a while now, so lets just see if
this thing floats. Announcing ...&lt;/p&gt;

&lt;h2&gt;Geeks on Bikes [0]&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/jurvetson/2471431044/&quot;&gt;&lt;img class='' src='http://farm3.static.flickr.com/2149/2471431044_7f6a52023c.jpg' width='' height='' alt='' title=''&gt;&lt;/a&gt;
&lt;em&gt;Photo credit: &lt;a href=&quot;http://www.flickr.com/photos/jurvetson/&quot;&gt;Steve Jurvetson&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ever noticed how geekdom and cycling seem to go hand in hand?  Perhaps it's
an appreciation of the design and engineering perfection of the humble bicycle,
or maybe the frittering of funds on gadgets leaves no other transport options.
Whatever the cause, on the whole, geeks like to bike.&lt;/p&gt;

&lt;p&gt;And so, fellow pedallers, I humbly invite you to lay down your arms in the
programming language / OS / editor wars and join me in the first of
hopefully many two wheeled forays in and around beautiful Churtown.&lt;/p&gt;

&lt;div&gt;&lt;figure role=code&gt;&lt;figcaption&gt;&lt;span&gt;Geeks on bikes[0] - geeks_on_bikes.js &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class='line'&gt;1&lt;/span&gt;
&lt;span class='line'&gt;2&lt;/span&gt;
&lt;span class='line'&gt;3&lt;/span&gt;
&lt;span class='line'&gt;4&lt;/span&gt;
&lt;span class='line'&gt;5&lt;/span&gt;
&lt;span class='line'&gt;6&lt;/span&gt;
&lt;span class='line'&gt;7&lt;/span&gt;
&lt;span class='line'&gt;8&lt;/span&gt;
&lt;span class='line'&gt;9&lt;/span&gt;
&lt;span class='line'&gt;10&lt;/span&gt;
&lt;span class='line'&gt;11&lt;/span&gt;
&lt;span class='line'&gt;12&lt;/span&gt;
&lt;span class='line'&gt;13&lt;/span&gt;
&lt;span class='line'&gt;14&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class='code' width='100%'&gt;&lt;pre&gt;&lt;code class='js'&gt;&lt;div class='line'&gt;&lt;span class=&quot;nx&quot;&gt;geeksOnBikes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;ride&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Bottle Lake Forest Loop&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s1&quot;&gt;&amp;#39;MTB&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;grade&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;Easy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// km (approx)&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;nx&quot;&gt;rendezvous&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;where&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;Beach Cafe, 16 Beach Rd, Nth New Brighton&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;when&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;s1&quot;&gt;&amp;#39;Sun Sep 11 14:00:00 NZST 2011&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;    &lt;span class=&quot;nx&quot;&gt;latlon&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;43.485248&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;172.722116&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/div&gt;&lt;div class='line'&gt;
&lt;/div&gt;&lt;div class='line'&gt;&lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;


&lt;p&gt;Bring yourself and steed.  Extra merit for GPS plots, helmet cams, Arduino
cycle computers, and other gadgetry.  Follow
&lt;a href=&quot;https://twitter.com/malclocke&quot;&gt;@malclocke&lt;/a&gt; for updates, I may postpone in the
event of atrocious weather.&lt;/p&gt;

&lt;p&gt;See you then!
&lt;/strike&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Mix and Mash Nominations</title>
    <link href="http://wholemeal.co.nz/blog/2011/08/06/mix-and-mash-nominations/"/>
    <updated>2011-08-06T21:25:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/08/06/mix-and-mash-nominations</id>
    <content type="html">&lt;p&gt;I'm very flattered to have received 2 nominations for the 'Best Mashup (so
far)' category for this years &lt;a href=&quot;http://www.mixandmash.org.nz/&quot;&gt;Mix and Mash&lt;/a&gt;
contest.&lt;/p&gt;

&lt;p&gt;The contest runs between August and September and challenges developers and
artists to create innovative work using open New Zealand data and content.&lt;/p&gt;

&lt;p&gt;As a prequel to the main event, there is a vote open for the best mash up so
far, for projects created before the contest period.&lt;/p&gt;

&lt;h2&gt;Darfield quake timeline&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://wholemeal.co.nz/~malc/darfield-earthquake-timeline/&quot;&gt;&lt;img class='' src='/images/darfield-earthquake-timeline-screenshot.jpg' width='' height='' alt='' title=''&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a little mashup page I made after the September 4th earthquake in
Christchurch.  It uses the data from &lt;a href=&quot;http://geonet.org.nz/&quot;&gt;Geonet&lt;/a&gt;, the New
Zealand geophysical information network, and the &lt;a href=&quot;http://code.google.com/p/timemap/&quot;&gt;Timemap.js&lt;/a&gt; library to display the initial aftershock
sequence from this earthquake as an interactive timeline.&lt;/p&gt;

&lt;p&gt;The most interesting thing about this simple project for me is that I was
contacted by Geonet and asked for permission to use the code on their own site,
and it's now present in the &lt;a href=&quot;http://geonet.org.nz/canterbury-quakes/timeline.html&quot;&gt;Canterbury quakes&lt;/a&gt;
section of their site.&lt;/p&gt;

&lt;p&gt;This is a great demonstration of the benefits of open data and open source in
combination.  Geonet provide open access to their quake data, allowing
developers to create interesting and useful tools around that data.  By making
my code available &lt;a href=&quot;https://github.com/malclocke/darfield-earthquake-timeline&quot;&gt;as open source software&lt;/a&gt;,
Geonet were free to incorporate it into their site.  This kind of 'round trip'
is what makes open data such a powerful concept.&lt;/p&gt;

&lt;h1&gt;Christchurch Metro&lt;/h1&gt;

&lt;p&gt;&lt;img class='left ' src='/images/christchurch-metro-icon.png' width='' height='' alt='' title=''&gt;&lt;/p&gt;

&lt;p&gt;My second nomination is for my
&lt;a href=&quot;https://market.android.com/details?id=nz.co.wholemeal.christchurchmetro&quot;&gt;Christchurch Metro Android app&lt;/a&gt;,
which uses real time data from the &lt;a href=&quot;http://metroinfo.co.nz/&quot;&gt;Metroinfo&lt;/a&gt;
system to display arrival times, route maps and other information for the local
bus service.&lt;/p&gt;

&lt;p&gt;This was a 'scratch an itch' project for me, to provide a solid Android
application for the Christchurch Metro, and also an opportunity to try out
Android development.  This project is also
&lt;a href=&quot;https://github.com/malclocke/ChristchurchMetro&quot;&gt;free and open source&lt;/a&gt; software.&lt;/p&gt;

&lt;p&gt;The competition is decided by public vote, and any votes for either the
&lt;a href=&quot;https://apps.facebook.com/promosapp/183177/entry/185321&quot;&gt;Darfield Earthquake Timeline&lt;/a&gt; or the
&lt;a href=&quot;https://apps.facebook.com/promosapp/183177/entry/185316&quot;&gt;Christchurch Metro app&lt;/a&gt; would be greatly
appreciated!&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>find_or_create - Did you find, or create?</title>
    <link href="http://wholemeal.co.nz/blog/2011/04/11/find_or_create-did-you-find-or-create/"/>
    <updated>2011-04-11T00:00:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/04/11/find_or_create-did-you-find-or-create</id>
    <content type="html">&lt;p&gt;&lt;code&gt;find_or_create_by_*&lt;/code&gt; is a great utility in the Rails toolbox.  It allows
you search for an object in the database by an arbitrary field, and if a
matching object is not found, a new one is created.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# If a user with the given email address is present in the database, it is&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# fetched and returned.  Otherwise, a new one is created and saved.&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_or_create_by_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;user@example.com&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;However, there does not appear to be a way to find out whether the object was
found, or whether a new one was created.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;One solution is to use the related &lt;code&gt;find_or_initialize_by_*&lt;/code&gt; method, which is
identical, except that is a matching record is found, a new object is returned&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_or_initialize_by_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;user@example.com&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_record?&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Do whatevahs ...&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here's my solution to doing it with &lt;code&gt;find_or_create&lt;/code&gt;.  It makes use of the fact
that an optional block can be passed to &lt;code&gt;find_or_create_by&lt;/code&gt;, which is only
executed when a matching record is &lt;strong&gt;not&lt;/strong&gt; found.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# A flag to store whether the record was created by find_or_create_by_*&lt;/span&gt;
  &lt;span class=&quot;kp&quot;&gt;attr_accessor&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:was_created&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;User&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find_or_create_by_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;user@example.com&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;was_created&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;was_created&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Do whatevahs&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;I'd be interested in alternative approaches.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>An Everyday Commute Through Quake Town</title>
    <link href="http://wholemeal.co.nz/blog/2011/04/09/an-everyday-commute-through-quake-town/"/>
    <updated>2011-04-09T00:00:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/04/09/an-everyday-commute-through-quake-town</id>
    <content type="html">&lt;p&gt;To help give people outside of Christchurch an understanding of how widespread
the effect of the Feb 22nd earthquake has been on Christchurch, I thought I'd
take some photo's of everything quake related that I see on my cycle commute
from the eastern suburbs into town.&lt;/p&gt;

&lt;p&gt;It's now nearly 6 weeks on from the quake, but the images below will hopefully
show how far we still have to go.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;These are by no means the worst of the devastation, but they represent what the
typical Christchurch resident will see on an average trip into town.  I didn't
deviate from my normal route to take any of these shots.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5473383932/&quot; title=&quot;Bowhill Road Fish and Chips by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5060/5473383932_2cc742ab7e.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;Bowhill Road Fish and Chips&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First up is our local chippy, about 100 metres from home.  Thankfully, all the
staff made it out unscathed.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602278861/&quot; title=&quot;IMG_5552 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5028/5602278861_45159778cf.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;IMG_5552&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a cell phone tower on wheels.  There's a generator inside, and some
kind of wireless uplink to the main network.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602329099/&quot; title=&quot;IMG_5423 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5187/5602329099_aca46ebb74.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5423&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason this temporary tower is in place, taken a few weeks before the rest
of these photos.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602860042/&quot; title=&quot;IMG_5553 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5146/5602860042_dbf74d438f.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;IMG_5553&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In many places along the Avon river, the river banks have slumped or collapsed,
in some cases several feet.  With winter weather approaching, there seems to
be a concerted effort to build up the banks to prevent flooding.  This is
the view west along the river from Wainoni bridge.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602271071/&quot; title=&quot;IMG_5554 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5189/5602271071_7cc4218d3f.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5554&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whilst most of the city has regained a water supply, some still haven't.  On
top of this, many peoples hot water systems require full mains pressure to work
correctly, and full water pressure has not returned to a lot of places.&lt;/p&gt;

&lt;p&gt;So there are several of these mobile showers available for residents around the
city.  This one is outside the Avonside Golf Course.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602267281/&quot; title=&quot;IMG_5555 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5143/5602267281_d9b334b292.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5555&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Drinking water for residents is available from large tanks in key locations.
These seem to be getting very little use now as mains water returns to more
and more homes.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602264535/&quot; title=&quot;IMG_5556 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5150/5602264535_297e644571.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;IMG_5556&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The worst hit areas are designated 'residents only', because heavy traffic
can cause further damage to already fragile houses.  This notice is still
in place from the September 2010 quake.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602261603/&quot; title=&quot;IMG_5557 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5146/5602261603_664b401887.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;IMG_5557&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The beaches and rivers are still no-go areas for recreation, and here's why.
The city's sewerage system is severely damaged.  The pipe at the bottom of the
shot is pumping raw you-know-what into the river, and is one of many sites
along the river and on the beaches where this is happening.&lt;/p&gt;

&lt;p&gt;The foot bridge in the background is also closed, as it contains a 66,000 volt
electricity cable, status unknown.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602256735/&quot; title=&quot;IMG_5558 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5265/5602256735_93ef338076.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;IMG_5558&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Post demolition, this is what remains of the average single story house.
Most of the houses that were badly damaged enough to warrant an immediate
demolition like this would have borne a 'red sticker', an 'absolutely no
entry' notice.  If that was the case, the house would have been demolished
with all of it's contents still inside.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602252715/&quot; title=&quot;IMG_5559 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5309/5602252715_3607ba7364.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5559&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More shoring of the river banks.  The river is still tidal at this point, and
at high tide the water level is already close to bursting on an average day.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602832576/&quot; title=&quot;IMG_5560 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm5.static.flickr.com/4095/5602832576_c47bf87b4e.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5560&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some areas are still without mains power.  Large generators like this one are
keeping the lights on for those neighbourhoods.  Our own street was on one of
these for the first two weeks after the quake.&lt;/p&gt;

&lt;p&gt;An ad hock community notice board has also popped up here.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602829700/&quot; title=&quot;IMG_5561 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5149/5602829700_300524bab3.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5561&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hadn't even noticed this house, behind a high fence, until the day I took
these photos and I was being more observant than usual.  This place used to be
two story, the lower floor has completely collapsed.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602242159/&quot; title=&quot;IMG_5562 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5266/5602242159_7f9949b443.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5562&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This place was a once grand 2 story residence that was fairly rough around
the edges before the quake.  It's days are numbered now, a large digger is
parked just out of shot ready to begin the demolition.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602238679/&quot; title=&quot;IMG_5564 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5021/5602238679_504ca3c5f6.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5564&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Demolition in progress.  I happened to ride past these shops on the corner of
Stanmore Road and Worcester Street at the moment they were pulling the roof
off.  Thankfully, as with a lot of the cities collapsed buildings, this row
of shops were already off limits before the February quake due to damage
sustained in September.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602820340/&quot; title=&quot;IMG_5565 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5023/5602820340_6178ab2acd.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5565&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The edge of the city cordon.  A very large area of the central city is still
off limits to the public.  Each entry point is manned by police and army
personnel.  This is the checkpoint on St Asaph and Barbadoes Streets.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602812830/&quot; title=&quot;IMG_5567 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm5.static.flickr.com/4101/5602812830_83a4b12149.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5567&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the stranger factors of all the damage is exposure of the inside of
peoples homes to the public gaze.  Here's someone's previously private bathroom
and toilet.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602810528/&quot; title=&quot;IMG_5568 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5064/5602810528_eb42f2f2f9.jpg&quot; width=&quot;500&quot; height=&quot;375&quot; alt=&quot;IMG_5568&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trents Wholesalers warehouse.  A goner.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;&lt;a href=&quot;http://www.flickr.com/photos/malclocke/5602806808/&quot; title=&quot;IMG_5569 by malclocke, on Flickr&quot;&gt;&lt;img class=&quot;flickr&quot; src=&quot;http://farm6.static.flickr.com/5309/5602806808_b0c90f37a0.jpg&quot; width=&quot;375&quot; height=&quot;500&quot; alt=&quot;IMG_5569&quot;&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Christchurch's biggest headache, the Hotel Grand Chancellor.  At 26 stories,
it's the cities second tallest building.  As is blatantly obvious from this
photo, it's not well.&lt;/p&gt;

&lt;p&gt;A few days after the quake, the collapsed corner of the hotel was temporarily
supported with new concrete struts to allow Urban Search and Rescue to enter
the building.&lt;/p&gt;

&lt;p&gt;The hotel lies in the heart of the city, and until it is demolished it's
likely at least two blocks either side of it will remain off limits for
everyone.  How the building is to be demolished safely is still, as far as
I'm aware, unknown.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Assert Difference With Multiple Count Values</title>
    <link href="http://wholemeal.co.nz/blog/2011/04/06/assert-difference-with-multiple-count-values/"/>
    <updated>2011-04-06T00:00:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/04/06/assert-difference-with-multiple-count-values</id>
    <content type="html">&lt;p&gt;&lt;code&gt;assert_difference&lt;/code&gt; is a really useful assertion baked in to Rails.  It
allows you to check that a value has changed by a given amount after a
block has been executed.&lt;/p&gt;

&lt;p&gt;Here's a pretty common use case, check a comment gets created in your
&lt;code&gt;CommentsControllerTest&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Make sure one new comment is created&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_difference&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Comment.count&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:comment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@comment_attributes&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You can also check that several different values change by a given amount:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Make sure one new comment and one notification email is created&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert_difference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Comment.count&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ActionMailer::Base.deliveries.size&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:comment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@comment_attributes&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;But, you cannot check if multiple values change by difference amounts, i.e.
check that 1 comment and 2 notification emails get created.&lt;/p&gt;

&lt;p&gt;The following method will allow you to do just that, drop it into
&lt;code&gt;test/test_helper.rb&lt;/code&gt; and you're away.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Runs assert_difference with a number of conditions and varying difference&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# counts.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Call as follows:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# assert_differences([[&amp;#39;Model1.count&amp;#39;, 2], [&amp;#39;Model2.count&amp;#39;, 3]])&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;assert_differences&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expression_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kp&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:binding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;expression_array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;expression_array&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each_with_index&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;difference&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pair&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inspect&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; didn&amp;#39;t change by &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;difference&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assert_equal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;before&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;difference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>Rendering From A Model In Rails 3</title>
    <link href="http://wholemeal.co.nz/blog/2011/04/05/rendering-from-a-model-in-rails-3/"/>
    <updated>2011-04-05T00:00:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/04/05/rendering-from-a-model-in-rails-3</id>
    <content type="html">&lt;p&gt;Despite the plethora of advice available on the net to never, ever, ever
render in a model, I still think there are occasional requirements to do
so.&lt;/p&gt;

&lt;p&gt;Here's one way to do it in Rails 3:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveRecord&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# Use the my_models/_my_model.txt.erb view to render this object as a string&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;to_s&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;ActionView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Rails&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;configuration&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;views&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;render&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;:partial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;my_models/my_model&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:txt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;ss&quot;&gt;:locals&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:my_model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>Making a ChangeLog with git and automake</title>
    <link href="http://wholemeal.co.nz/blog/2011/02/07/making-a-changelog-with-git-and-automake/"/>
    <updated>2011-02-07T00:00:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2011/02/07/making-a-changelog-with-git-and-automake</id>
    <content type="html">&lt;p&gt;Here's my solution to this, based upon the solution from &lt;a href=&quot;http://erikhjortsberg.blogspot.com/2010/06/using-automake-to-generate-changelog.html&quot;&gt;Erik Hjortsberg&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This will only get called by &lt;code&gt;make dist&lt;/code&gt; or &lt;code&gt;make distcheck&lt;/code&gt; and will only get updated when &lt;code&gt;configure.ac&lt;/code&gt; gets updated, which is where I increment my release version numbers.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;make&quot;&gt;&lt;span class=&quot;c&quot;&gt;# In the top level Makefile.am&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;dist-hook&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;ChangeLog&lt;/span&gt;

&lt;span class=&quot;nf&quot;&gt;ChangeLog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;configure.ac&lt;/span&gt;
    git log --stat --name-only --date&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;short --abbrev-commit &amp;gt; ChangeLog
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>No changes - did you forget to use 'git add'?</title>
    <link href="http://wholemeal.co.nz/blog/2010/06/11/no-changes-did-you-forget-to-use-git-add/"/>
    <updated>2010-06-11T00:00:00+12:00</updated>
    <id>http://wholemeal.co.nz/blog/2010/06/11/no-changes-did-you-forget-to-use-git-add</id>
    <content type="html">&lt;p&gt;Generally the error messages from git are fairly helpful, and often guide you
to a resolution.  Occasionally, they're not.&lt;/p&gt;

&lt;!-- more --&gt;


&lt;p&gt;I ran across this little problem today during a rebase.  When a conflict occurs
during a rebase, you are asked to resolve it manually and then use &lt;code&gt;git
rebase --continue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you decide during the conflict resolution to scrap the checked out branch changes, and just keep the file as-is from the other branch, you may get a little confused.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; git rebase otherbranch
&lt;span class=&quot;go&quot;&gt;First, rewinding head to replay your work on top of it...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Applying: This change will create a conflict during rebase&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Using index info to reconstruct a base tree...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Falling back to patching base and 3-way merge...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Auto-merging foo.txt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;CONFLICT (content): Merge conflict in foo.txt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Failed to merge in the changes.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Patch failed at 0001 Commit message from checked out branch which creates conflict&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;When you have resolved this problem run &amp;quot;git rebase --continue&amp;quot;.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;If you would prefer to skip this patch, instead run &amp;quot;git rebase --skip&amp;quot;.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;To restore the original branch and stop rebasing run &amp;quot;git rebase --abort&amp;quot;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ok, have a look at the conflict.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat foo.txt 
&lt;span class=&quot;go&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Foo&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;=======&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Bar&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&lt;/span&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; Commit message from checked out branch which creates conflict
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Here, &lt;code&gt;HEAD&lt;/code&gt; is the other branch version, not the one that is checked out.&lt;/p&gt;

&lt;p&gt;I decide I want to keep the 'otherbranch' version and drop all of the changes I've made on the checked out branch&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Foo&amp;quot;&lt;/span&gt; &amp;gt; foo.txt 
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; git rebase --continue
&lt;span class=&quot;go&quot;&gt;You must edit all merge conflicts and then&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;mark them as resolved using git add&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Ok, so I need to tell git the conflict is resolved, makes sense.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; git add foo.txt
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; git rebase --continue
&lt;span class=&quot;go&quot;&gt;Applying: This change will create a conflict during rebase&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;No changes - did you forget to use &amp;#39;git add&amp;#39;?&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;When you have resolved this problem run &amp;quot;git rebase --continue&amp;quot;.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;If you would prefer to skip this patch, instead run &amp;quot;git rebase --skip&amp;quot;.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;To restore the original branch and stop rebasing run &amp;quot;git rebase --abort&amp;quot;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Huh?!?  No, I didn't forget to use &lt;code&gt;git add&lt;/code&gt;, I did it ... like ... 2 seconds
ago!&lt;/p&gt;

&lt;p&gt;Turns out that because there is no change from the patch git suspects something
has gone wrong.  Git expects a patch to have been applied, but the file has
remained unchanged.&lt;/p&gt;

&lt;p&gt;The error message is not very intuitive, but it does contain the answer.  We
just need to tell rebase to skip this patch.  It's also not necessary to fix
the conflict markers in the file.  You will end up with the file version from
the branch you are rebasing on.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;console&quot;&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; git rebase --skip
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;



</content>
  </entry>
  
  <entry>
    <title>Active Resource - Associations and Nested Resources</title>
    <link href="http://wholemeal.co.nz/blog/2010/03/08/active-resource-associations-and-nested-resources/"/>
    <updated>2010-03-08T00:00:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2010/03/08/active-resource-associations-and-nested-resources</id>
    <content type="html">&lt;p&gt;I've been working on a &lt;a href=&quot;http://github.com/malclocke/pivotal_tracker&quot;&gt;wrapper library&lt;/a&gt; for the &lt;a href=&quot;http://www.pivotaltracker.com/&quot;&gt;Pivotal Tracker&lt;/a&gt; API, and found it difficult to find a single source of documentation on how to map deep nested restful Rails routes into ARes classes.&lt;/p&gt;

&lt;p&gt;Using the classic 'Blog posts' and 'Comments' as an example, you have RESTful URL's like these to work with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/posts
/posts/1
/posts/1/comments
/posts/1/comments/1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The documentation is a little hazy on how you map these, in particular the 'comments', in ARes.&lt;/p&gt;

&lt;p&gt;After a little poking around, I've come up with the following solution:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveResource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://site.com/&amp;quot;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;scope&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:params&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:post_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Comment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;ActiveResource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;Base&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# :post_id gets swapped out by ARes based on the :prefix_options hash&lt;/span&gt;
  &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;site&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://site.com/posts/:post_id&amp;quot;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;post&lt;/span&gt;
    &lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix_options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:post_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prefix_options&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:post_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;You can then use these classes like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# Find post id 1&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Find all comments for a post&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comments&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;body&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Find comment id 1 for a post&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a new comment and assign it to a post&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;Comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;body_text&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;post&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;post&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;comment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;The key to all this is the &lt;code&gt;:prefix_options&lt;/code&gt; hash, which is not very well documented, and allows you to create the 'belongs_to' relationship which nested resources typically represent in a Rails app.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>A week of geek</title>
    <link href="http://wholemeal.co.nz/blog/2010/01/09/a-week-of-geek/"/>
    <updated>2010-01-09T00:00:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2010/01/09/a-week-of-geek</id>
    <content type="html">&lt;p&gt;Jan 17th - 24th 2010 is going to be a busy week, as I'll be attending both the &lt;a href=&quot;http://www.lca2010.org.nz/&quot;&gt;linux.conf.au&lt;/a&gt; and &lt;a href=&quot;http://wellington2010.drupalsouth.net.nz/&quot;&gt;Drupal South&lt;/a&gt; conferences back to back.&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;It looks set to be a great week to showcase Free and Open Source Software in the capital, with some of the big hitters from the Linux and Drupal communities in attendance.&lt;/p&gt;

&lt;p&gt;If you'd like to meet up for a chat, please &lt;a href=&quot;/contact&quot;&gt;contact me&lt;/a&gt; and let me know.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>New site launch: slynkey.com</title>
    <link href="http://wholemeal.co.nz/blog/2010/01/04/new-site-launch-slynkey-com/"/>
    <updated>2010-01-04T00:00:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2010/01/04/new-site-launch-slynkey-com</id>
    <content type="html">&lt;p&gt;We're pleased to announce a new site release for the new year, the womens magazine and community website &lt;a href=&quot;http://slynkey.com/&quot;&gt;slynkey.com&lt;/a&gt;&lt;/p&gt;

&lt;!--more--&gt;


&lt;p&gt;The site development was an interesting project because it involved a large content and user base migration from an existing Joomla! based website.  Whilst we don't usually recommend a platform migration for a site of this size, the platform was proving to be a real problem for the client.&lt;/p&gt;

&lt;p&gt;The decision to move to &lt;a href=&quot;http://drupal.org/&quot;&gt;Drupal&lt;/a&gt; was a fairly easy one.  The following aspects of the site made it an excellent choice for Drupal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The site has a very large user base, and has a vibrant community of readers.&lt;/li&gt;
&lt;li&gt;The site has a large number of contributing authors, with various levels of access required.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;Challenges&lt;/h3&gt;


&lt;p&gt;There were a few challenges surrounding the site build.&lt;/p&gt;

&lt;h4&gt;Data migration&lt;/h4&gt;


&lt;p&gt;The site had a very large user base to import, and a large number of archived articles.  Wholemeal updated &lt;a href=&quot;http://drupal.org/project/joomla&quot;&gt;an existing Joomla import module&lt;/a&gt;, porting it to Drupal 6.x and implementing a lot of new functionality and bug fixes, and submitting the code back to the community which, judging by the &lt;a href=&quot;http://drupal.org/project/usage/joomla&quot;&gt;project usage statistics&lt;/a&gt;, have proved fairly popular (we started working on the module in July 2009).&lt;/p&gt;

&lt;h4&gt;Contextual content&lt;/h4&gt;


&lt;p&gt;Another challenge was serving contextual content to users, both anonymous and logged in.  The site is highly targeted, with users selecting their home town and being served specific content and advertisements related to their location.  This gives the site a great marketing lead over its competitors, but proved to be a technical challenge.  Thankfully, Drupal provided ample flexibility to solve these challenges.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>New project: DogSheet</title>
    <link href="http://wholemeal.co.nz/blog/2009/12/05/new-project-dogsheet/"/>
    <updated>2009-12-05T00:00:00+13:00</updated>
    <id>http://wholemeal.co.nz/blog/2009/12/05/new-project-dogsheet</id>
    <content type="html">&lt;p&gt;We've been working away for a while on a new &lt;a
href=&quot;http://rubyonrails.org/&quot;&gt;Ruby on Rails&lt;/a&gt; project, and have decided to
release it under the &lt;acronym title=&quot;GNU Public License&quot;&gt;GPL&lt;/acronym&gt;.  Check
it out on &lt;a href=&quot;http://github.com/malclocke/dogsheet&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The project will scratch an itch we have for tracking time against stories in
&lt;a href=&quot;http://pivotaltracker.com&quot;&gt;Pivotal Tracker&lt;/a&gt;, a project management
application for agile development.  It's still in it's infancy at the moment,
but development is moving along at the pace you would expect from a Rails app,
keep an eye on the project if you're looking for the worlds greatest time
tracker!&lt;/p&gt;
</content>
  </entry>
  
</feed>

