codahale.com٭blog

Coda Hale lives in Berkeley, CA, where he writes about Ruby on Rails, usability, web design and development, and the occasional bit about bicycles.

Singletons: Only The Lonely

I’ve never really spent much time on design patterns, but recently I’ve been reading Head First Design Patterns and I can’t help but notice how much easier Ruby makes certain patterns. Composition over inheritance becomes as easy as sneezing with mixins, and the thoughtful Ruby folks have already implemented quite a few.

I don’t use Singleton as much as I should (preferring instead to just stuff all the methods in the class), but for objects which have an expensive or complicated instantiation method, it’s extremely useful. (I mean, that’s why it’s a pattern, right?) Also, the Singleton mixin takes care of all the threading complications to which Singletons often fall prey.

But effective and useful it may be, Singleton is ugly, and for one big reason: instance. I hate typing instance all over the place, and it’s been a big stumbling block in my acceptance of the Singleton mixin. I understand why it’s there–the pattern doesn’t mention moving methods from instance to class scope–but on a syntactic level it irks me. If I’m using a singleton, I really shouldn’t need to know that it is a singleton–it could be a magic happy fairy princess castle for thread-safe methods, for all I care.

So yeah, I went and did something about it. I combined the power of Singleton and Proxy. Check it out:

module Singleton
  class << self
    def included_with_proxy(base)
      included_without_proxy(base)
      base.class_eval do
        class << self
          def method_missing_with_proxy(m, *args)
            if instance.respond_to?(m)
              instance.send(m, *args)
            else
              method_missing_without_proxy(m, *args)
            end
          end
          alias_method_chain :method_missing, :proxy

          def methods_with_proxy
            return (methods_without_proxy + instance.methods).uniq
          end
          alias_method_chain :methods, :proxy

          def respond_to_with_proxy?(m)
            return respond_to_without_proxy?(m) || instance.respond_to?(m)
          end
          alias_method_chain :respond_to?, :proxy
        end
      end
    end
    alias_method_chain :included, :proxy
  end
end

You’ll need to require singleton and activesupport for this one, and since it uses alias_method_chain, you’ll need to either be running Rails edge or grab it from the source.

What it does is pretty simple: if it’s not already a class method, Singleton passes it on to its instance:

class Magician
  include Singleton

  def dove
    "*poof* A dove!"
  end

  def segway
    "*rides Segway around*"
  end
end

Magician.dove   #=> "*poof* A dove!"
Magician.segway #=> "*rides Segway around*"

No more instance, though it’s there if you need it.

14 comments »

Rails programmer needed!

So I’m going to be leaving Gilsson shortly for a new startup in Berkeley, which means that my old job is now open. If you’re within commuting distance from Hayward, CA and are looking for a Rails/IT position, check this out:

Responsibilities:

  • Maintain local network of 5-10 workstations and 1-2 file and database servers, with a mix of Windows XP and Linux.
  • Improve and extend our Rails-powered e-commerce codebase, eventually rolling out new versions of two of our online stores.
  • Improve and maintain our Rails-powered product management database.
  • Maintain our Fedora Core 5 production Rails web server (Apache 2.2 + Mongrel, natch).
  • Develop custom applications for in-house use.

Requirements:

  • Strong experience with Ruby on Rails, web development and associated technologies, including Javascript, XHTML/CSS, XML, AJAX/AHAH, and RSS.
  • Experience with SQL in general, and using and configuring MySQL specifically.
  • Experience with e-commerce.
  • Commitment to web standards and accessibility.
  • Experience with test-driven development.
  • Familiarity with Subversion and Trac a plus.
  • Ability to be self-directed, complete tasks with minimal management oversight.
  • Flexibility and good on-the-fly problem-solving skills.

It’s a great place to work, and Ming (the CEO) is an awesome boss. There’s a lot of flexibility in work hours, and a lot of autonomy in the position–you get problems, you make solutions. (Plus, if you apply, you’ll probably get to meet me.) All of the code is well-documented, and all the important bits have full test coverage–no Daily WTF material here.

If this sounds like your kind of gig, email your resume to ming@gilsson.com with the subject line “IT Manager”. If you have any questions about the job, email me and I’ll do my best to answer them.

Regarding the new job, I’m going to be doing some Rails programming with a small team of people who I really admire, including the author of one of the books on my desk right now. I guess that’s one book I can leave for the new person… ;-)

2 comments »

Le Tour De WTF

Okay, so right off the bat, Hincapie disappears in a puff of disappointment–the guy at the Link said he lost too much weight too quickly, and he’s down to like 155lbs, which for a guy who’s just a touch shorter than I am is Jack The Pumpkin King territory–and Landis, after having dropped a bomb (”oh, bee-tee-dub, I’ve got the hips of an 80-year old woman who’s allergic to calcium”), somehow pops to the top! I’m happy to see a Yank in the front, but I’m kind of confused–a “destroyed” hip joint and a yellow jersey seem like they’d clash. Then in Stage 16, Landis conks out in the Alps and drops a full eight minutes behind the leader, kind of killing his shot at the Tour.

That’s more like it, I thought, that’s the familiar disappointment that I’d managed to not feel for the past seven years.

Until I crack open the Bloglines this morning to find this:

American Floyd Landis (Phonak) chased down and destroyed an 11-man breakaway, then soloed away to win the 17th stage of the Tour de France Thursday in Morzine after 200.5km of racing on the final day in the Alps.

He goes from bonking out in the Alps to some kind of Robocop-in-bicycle-mode breakaway in less than a day. And this isn’t just a last gasp on his way out–he put almost six whole minutes of shame in everyone else’s game, and now he’s 30 seconds away from the yellow jersey again.

God, I’m almost happy Lance retired–this is an amazing Tour.

3 comments »