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

  <title>paul.annesley.cc</title>
  <link href="http://paul.annesley.cc/atom.xml" rel="self"/>
  <link href="http://paul.annesley.cc/"/>
  <updated>2012-01-09T19:18:13+11:00</updated>
  <id>http://paul.annesley.cc/</id>
  <author>
    <name>Paul Annesley</name>
    
  </author>

  
  <entry>
    <title>MethodHuntingDelegator</title>
    <link href="http://paul.annesley.cc/2012/01/methodhuntingdelegator"/>
    <updated>2012-01-09T17:51:00+11:00</updated>
    <id>http://paul.annesley.cc/2012/01/methodhuntingdelegator</id>
    <content type="html">&lt;p&gt;I was implementing search in a Ruby app where the results objects were instances
of a mix of model classes. Each one had what could be considered a title and a
description, but the method names were inconsistent.&lt;/p&gt;

&lt;p&gt;Wrapping each result in a &lt;code&gt;SearchResult&lt;/code&gt; decorator to normalize the interface
seemed like a good idea. Ruby provides an abstract &lt;a href=&quot;http://www.ruby-doc.org/stdlib-1.9.3/libdoc/delegate/rdoc/Delegator.html&quot;&gt;Delegator&lt;/a&gt; and a concrete
&lt;a href=&quot;http://www.ruby-doc.org/stdlib-1.9.3/libdoc/delegate/rdoc/SimpleDelegator.html&quot;&gt;SimpleDelegator&lt;/a&gt; which gets most of the way there.&lt;/p&gt;

&lt;p&gt;To normalize the method interface, I wrote an extension of &lt;code&gt;SimpleDelegator&lt;/code&gt;
with a &lt;code&gt;#hunt_and_call(*candidates)&lt;/code&gt; method, which finds and calls the first
method of the candidate list which the delegate responds to.&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s the example calling code:&lt;/p&gt;

&lt;div&gt;&lt;script src=&#8217;https://gist.github.com/1581535.js?file=example.rb&#8217;&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;class Book &amp;lt; SomeModelThing
  attr_reader :title, :blurb
end

class Course &amp;lt; SomeModelThing
  attr_reader :name, :description
end

class SearchResult &amp;lt; MethodHuntingDelegator

  def description
    hunt_and_call :description, :blurb
  end

  def title
    hunt_and_call :title, :name
  end

end

# simulate the results of a search with mixed result types
results = [ Book.first, Course.first ].map(&amp;amp;SearchResult.method(:new))

results.each { |r| puts &amp;quot;#{r.title}: #{r.description}&amp;quot; }&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;And the MethodHuntingDelegator implementation:&lt;/p&gt;

&lt;div&gt;&lt;script src=&#8217;https://gist.github.com/1581535.js?file=method_hunting_delegator.rb&#8217;&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;require &amp;quot;delegate&amp;quot;

class MethodHuntingDelegator &amp;lt; SimpleDelegator

  def hunt_and_call *candidates
    hunt_method(*candidates).call
  end

  private

  def hunt_method *candidates
    __getobj__.method candidates.detect(
      -&amp;gt;{ raise Error.new(candidates, __getobj__) },
      &amp;amp;__getobj__.method(:respond_to?)
    )
  end

  class Error &amp;lt; StandardError
    def initialize candidates, object
      super &amp;quot;#{candidates.inspect} not implemented by #{object.inspect}&amp;quot;
    end
  end

end&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;And of course:&lt;/p&gt;

&lt;div&gt;&lt;script src=&#8217;https://gist.github.com/1581535.js?file=method_hunting_delegator_spec.rb&#8217;&gt;&lt;/script&gt;
&lt;noscript&gt;&lt;pre&gt;&lt;code&gt;require &amp;quot;spec_helper&amp;quot;
require &amp;quot;method_hunting_delegator&amp;quot;

describe MethodHuntingDelegator do

  context &amp;quot;decorating a string&amp;quot; do

    let(:delegate) { &amp;quot;abcd&amp;quot; }
    let(:delegator) { MethodHuntingDelegator.new(delegate) }

    describe &amp;quot;#hunt_and_call&amp;quot; do

      it &amp;quot;delegates [ :not_a_method, :length, :upcase ] to String#length&amp;quot; do
        delegator.hunt_and_call(:not_a_method, :length, :upcase).should == 4
      end

      it &amp;quot;raises MethodHuntingDelegator::Error for [ :nope_A, :nope_B ]&amp;quot; do
        expect do
          delegator.hunt_and_call(:nope_A, :nope_B)
        end.to raise_error(MethodHuntingDelegator::Error)
      end

    end

  end

end&lt;/code&gt;&lt;/pre&gt;&lt;/noscript&gt;&lt;/div&gt;


&lt;p&gt;Completely insane? Useful enough for a gem? Better way of going about it? Give
me hell in &lt;a href=&quot;https://gist.github.com/1581535&quot;&gt;the gist comments&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Camera Buyers Guide — The Verge</title>
    <link href="http://paul.annesley.cc/2012/01/camera-buyers-guide-the-verge"/>
    <updated>2012-01-09T10:50:00+11:00</updated>
    <id>http://www.theverge.com/2012/1/2/2663464/camera-buyers-guide</id>
    <content type="html">&lt;p&gt;Ridiculously good article on digital cameras at &lt;a href=&quot;http://www.theverge.com/about-the-verge&quot;&gt;The Verge&lt;/a&gt;, worth reading
even if you&amp;#8217;re not in the market for one.&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;What we’re seeking to do here is help you make an informed decision by
separating the meaningful data from the meaningless. This is a guide to
discerning the things that will make a recognizable difference in your
photographic experience and results. We’ve selected a few of our favorite
cameras in the categories below, but those will change over time, whereas the
rest of this advice will (hopefully) remain relevant for a long time to come.&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Why can&amp;#8217;t there be more content of this quality on the Internet?&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Todokyo</title>
    <link href="http://paul.annesley.cc/2011/02/11-todokyo"/>
    <updated>2011-02-11T11:24:53+11:00</updated>
    <id>http://todokyo.com/</id>
    <content type="html">&lt;p&gt;Interesting looking todo client-side web app..&lt;/p&gt;

&lt;blockquote&gt;
It works like you’d expect, with a couple restrictions: First, every morning it starts over fresh. Your list from the day before is thrown in the trash. This, hopefully, will encourage the completion of all tasks each day and discourage the addition of frivolous items. Second, there’s no reordering. I want to trust my subconscious; if I add a task before another, then it’s because my mind has determined it’s priority by remembering it sooner.
&lt;/blockquote&gt;


&lt;p&gt;via &lt;a href=&quot;http://twitter.com/toolmantim/status/35851627713798144&quot;&gt;@toolmantim&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Email with Amazon SES and Rails 3</title>
    <link href="http://paul.annesley.cc/2011/02/06-email-with-amazon-ses-and-rails-3"/>
    <updated>2011-02-06T19:48:31+11:00</updated>
    <id>http://robots.thoughtbot.com/post/3105121049/delivering-email-with-amazon-ses-in-a-rails-3-app</id>
    <content type="html">&lt;p&gt;The always excellent GIANT ROBOTS describes using Amazon&amp;#8217;s new Simple Email Service for sending mail from Rails 3, using the aws-ses gem.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>An intro to modern OpenGL</title>
    <link href="http://paul.annesley.cc/2010/05/12-opengl-es-20-tutorial"/>
    <updated>2010-05-12T21:29:00+10:00</updated>
    <id>http://duriansoftware.com/joe/An-intro-to-modern-OpenGL.-Table-of-Contents.html</id>
    <content type="html">&lt;p&gt;An excellent OpenGL tutorial; beware other documentation and tutorials which endorse deprecated APIs and practices.&lt;/p&gt;

&lt;p&gt;Modern enough to be applicable to OpenGL ES 2.0 (and therefore &lt;a href=&quot;http://en.wikipedia.org/wiki/WebGL&quot;&gt;WebGL&lt;/a&gt;), which requires vertex and fragment shaders to be written in &lt;a href=&quot;http://en.wikipedia.org/wiki/WebGL&quot;&gt;OpenGL Shader Language&lt;/a&gt; to take advantage of the programmable rendering pipeline, and which removes much of the procedural (glBegin/glEnd) API.&lt;/p&gt;

&lt;p&gt;Adapting this tutorial to Cocoa Touch for iPhone/iPad OpenGL ES 2.0 development was relatively easy, and beat any iPhone OS specific documentation for ES 2.0 that I&amp;#8217;ve found.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>git-ff for git 1.7+</title>
    <link href="http://paul.annesley.cc/2010/05/12-git-ff"/>
    <updated>2010-05-12T20:07:00+10:00</updated>
    <id>http://gist.github.com/398090</id>
    <content type="html">&lt;p&gt;Provides &amp;#8216;git ff&amp;#8217; to quickly fast-forward your current branch to the tracked remote when possible.&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s &amp;#8216;git pull &amp;#8211;ff-only&amp;#8217; for those who do their own fetching, and besides, &amp;#8216;git ff&amp;#8217; is quicker :)&lt;/p&gt;

&lt;p&gt;Drop it in your path somewhere; depends on Git 1.7+ for the new &amp;#8211;ff-only parameter.&lt;/p&gt;

&lt;script src=&quot;http://gist.github.com/398090.js?file=git-ff&quot;&gt;&lt;/script&gt;

</content>
  </entry>
  
  <entry>
    <title>mustache: logic-less templates</title>
    <link href="http://paul.annesley.cc/2010/03/30-mustache-templates"/>
    <updated>2010-03-30T21:18:00+11:00</updated>
    <id>http://defunkt.github.com/mustache/</id>
    <content type="html">&lt;p&gt;Nice simple template format, implementations in Ruby, Python, JavaScript, PHP and more.
Similar to Django templates in simplicity, syntax and sensible constraint of logic.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>toto</title>
    <link href="http://paul.annesley.cc/2010/02/toto"/>
    <updated>2010-02-10T00:46:19+11:00</updated>
    <id>http://github.com/cloudhead/toto</id>
    <content type="html">&lt;p&gt;Tiny blog engine in Ruby and Rack, uses flat git-managed content files containing YAML &amp;amp; ERB/Markdown, handles comments via disqus, leaves caching to HTTP.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Machinarium</title>
    <link href="http://paul.annesley.cc/2010/01/machinarium"/>
    <updated>2010-01-22T14:03:56+11:00</updated>
    <id>http://machinarium.net/demo/</id>
    <content type="html">&lt;p&gt;A puzzle point-and-click adventure game with a nice ambient soundtrack and a Oddworld: Abe&amp;#8217;s Oddysee feel about it. Implemented in flash, free demo.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Semantic Versioning</title>
    <link href="http://paul.annesley.cc/2009/12/semantic-versioning"/>
    <updated>2009-12-16T14:13:37+11:00</updated>
    <id>http://semver.org/</id>
    <content type="html">&lt;p&gt;Simple version number specification for systems which expose a public API.  The format is major.minor.patch (e.g. 3.0.12); major indicates backwards incompatible, minor indicates backwards compatible, and 0.x.x indicates rapid development.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>The Go Programming Language</title>
    <link href="http://paul.annesley.cc/2009/11/the-go-programming-language"/>
    <updated>2009-11-11T16:05:50+11:00</updated>
    <id>http://golang.org/</id>
    <content type="html">&lt;p&gt;New programming language from Google: performance like C, dynamic like Python, concurrent like Erlang.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>node.js</title>
    <link href="http://paul.annesley.cc/2009/11/node-js"/>
    <updated>2009-11-10T10:18:13+11:00</updated>
    <id>http://nodejs.org/</id>
    <content type="html">&lt;p&gt;Event driven network IO for V8 JavaScript.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>v8 JavaScript Engine</title>
    <link href="http://paul.annesley.cc/2009/11/v8-javascript-engine"/>
    <updated>2009-11-10T10:17:01+11:00</updated>
    <id>http://code.google.com/p/v8/</id>
    <content type="html">&lt;p&gt;Google&amp;#8217;s JavaScript engine as seen in Chrome, runs standalone or embedded in C++&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>jaml - GitHub</title>
    <link href="http://paul.annesley.cc/2009/11/jaml-github"/>
    <updated>2009-11-09T09:04:33+11:00</updated>
    <id>http://github.com/edspencer/jaml</id>
    <content type="html">&lt;p&gt;Jaml tries to emulate Ruby’s Haml library, making it easy to generate HTML in your JavaScript projects.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Conflict free DNS and routes with multiple DHCP interfaces</title>
    <link href="http://paul.annesley.cc/2009/10/conflict-free-dns-routes-multiple-dhcp-interfaces"/>
    <updated>2009-10-27T11:57:00+11:00</updated>
    <id>http://paul.annesley.cc/2009/10/conflict-free-dns-routes-multiple-dhcp-interfaces</id>
    <content type="html">&lt;h2&gt;The Problem&lt;/h2&gt;

&lt;p&gt;Running DHCP on two or more network interfaces inevitably leads to 
conflicting or unpredictable DNS and default route settings.&lt;/p&gt;

&lt;p&gt;For development at home and work, I use an Ubuntu virtual machine running 
on Mac OS.  To ensure I have a predictable IP address regardless of what 
network I&amp;#8217;m on, the VM primary network interface is &lt;strong&gt;NATed&lt;/strong&gt;, so 
it gets an IP address from VMware&amp;#8217;s DHCP server.  To let my co-workers access 
HTTP on my virtual machine, I have a second network interface which is 
&lt;strong&gt;bridged&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The biggest symptom of the problem is complete loss of connectivity when 
I switch between home and office, and the default route from the previous 
location is retained.&lt;/p&gt;

&lt;h2&gt;The Solution That Should Work&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://linux.die.net/man/5/dhclient.conf&quot;&gt;DHCP client configuration&lt;/a&gt;
lets you specify which details you want to request from the DHCP server.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;strong&gt;request&lt;/strong&gt; statement&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;request [ option ] [, &amp;#8230; option ];&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The request statement causes the client to request that any server 
responding to the client send the client its values for the specified 
options. Only the option names should be specified in the request statement 
- not option parameters. By default, the DHCP server requests the subnet-mask, 
broadcast-address, time-offset, routers, domain-name, domain-name-servers, 
host-name, nis-domain, nis-servers, and ntp-servers options.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So it should be possible to omit &amp;#8216;routers&amp;#8217; and &amp;#8216;domain-name-servers&amp;#8217; from 
the &amp;#8216;request&amp;#8217; statement of the bridged interface, and all should be good.
However, it seems that some DHCP servers (like in my Linksys router at home) 
send a &amp;#8216;router&amp;#8217; anyway, and the DHCP client respects it despite not having 
requested it.&lt;/p&gt;

&lt;h2&gt;The Solution That Does Work&lt;/h2&gt;

&lt;p&gt;The solution that seems to work reliably is to write a simple 
dhclient-enter-hook to unset any unwanted details before they are 
processed.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;
# /etc/dhcp3/dhclient-enter-hooks.d/bridged-eth1

if [ &quot;$interface&quot; = eth1 -a -n &quot;$new_routers&quot; ]; then
        echo Discarding eth1 routers: $new_routers
        unset new_routers
fi
if [ &quot;$interface&quot; = eth1 -a -n &quot;$new_domain_name_servers&quot; ]; then
        echo Discarding eth1 dns servers: $new_domain_name_servers
        unset new_domain_name_servers
fi
&lt;/code&gt;&lt;/pre&gt;
</content>
  </entry>
  
  <entry>
    <title>proxymachine - GitHub</title>
    <link href="http://paul.annesley.cc/2009/10/proxymachine-github"/>
    <updated>2009-10-22T11:46:43+11:00</updated>
    <id>http://github.com/mojombo/proxymachine</id>
    <content type="html">&lt;p&gt;Awesome looking Ruby/EventMachine TCP proxy from GitHub that does content-based routing to a backend. Opens a proxy to a backend once the read buffer contains enough information for a ruby block to return the desired backend address.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>sstrudeau&#8217;s jquery-dropper at master - GitHub</title>
    <link href="http://paul.annesley.cc/2009/10/sstrudeau-jquery-dropper-at-master-github"/>
    <updated>2009-10-15T18:27:01+11:00</updated>
    <id>http://github.com/sstrudeau/jquery-dropper</id>
    <content type="html">&lt;p&gt;jQuery plugin, uses Canvas to provide an &amp;#8220;eye dropper&amp;#8221; color picker for same-domain images based on their pixel data.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Cloudvox - API-driven phone calls</title>
    <link href="http://paul.annesley.cc/2009/10/cloudvox-api-driven-phone-calls"/>
    <updated>2009-10-12T21:37:01+11:00</updated>
    <id>http://cloudvox.com/</id>
    <content type="html">&lt;p&gt;Make and receive calls with JSON over RESTful HTTP, with flexible pricing.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Unicorn! - GitHub</title>
    <link href="http://paul.annesley.cc/2009/10/unicorn-github"/>
    <updated>2009-10-12T17:19:32+11:00</updated>
    <id>http://github.com/blog/517-unicorn</id>
    <content type="html">&lt;p&gt;GitHub on their switch from nginx-&gt;haproxy-&gt;mongrel to nginx-&gt;unicorn stack, and why the Unicorn model rocks.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>gRaphaÃ«l â Charting JavaScript Library</title>
    <link href="http://paul.annesley.cc/2009/10/grapha-charting-javascript-library"/>
    <updated>2009-10-08T10:48:56+11:00</updated>
    <id>http://g.raphaeljs.com/</id>
    <content type="html">&lt;p&gt;Graph and chart plugin for Raphaël, by Dmitry Baranovskiy.&lt;/p&gt;
</content>
  </entry>
  
</feed>

