The Monkey, Refined

(ruby, monkey-patching, refinements, metaprogram all the things)
()

Monkey-patching. It strikes fear into newcomers to Ruby, excitement and abandon in moderate Ruby developers, and sad, disgruntled sighs from the experienced developers who end up having to wade through a huge Rails codebase to find out where somebody decided to monkey-patch the mysql2 gem in a way that makes it incompatible with a Rails 4 upgrade (bonus points for hiding the patch in something like app/models/stats/nightly_stats_run/customer_roi.rb, obviously).

(bitter tears of experience here)

But hark! Ruby 2.1 is here, and may contain some salvation in the form of refinements. First, though, a refresher.

Patch that Monkey!

Monkey-patching in Ruby involves modifying code at run-time, either by extending and providing additional functionality or redefining existing code. And Ruby makes it so easy! Consider this little gem:

class String
  def all_is_love
    ‘❤’ * self.length
  end
end

This extends String with the method :all_is_love, so:

pry(main)> 'hello'.all_is_love                                              
=> "❤❤❤❤❤”

This is how large chunks of the Rails helper methods (e.g. :camelize) are implemented. And this is fine…except due to the Magic of Ruby, you can do this pretty much anywhere in your code. And you can do this as well:

class String
  def length
    2
  end
end

pry(main)> 'hello’.length                                              
=> 2

Just to give you an idea of the systemic breakdown this can create, let’s go back to our earlier method:


pry(main)> 'hello'.all_is_love
=>"❤❤”

Again, there are sometimes reasons why you have to monkey-patch and replace methods at runtime. Perhaps your database connection has some legacy weirdness that needs to be worked around and it isn’t covered by a standard gem (this is a code smell, obviously, but sometimes it has to be done). Being able to do this at-will in a large code-base, however, can easily lead to problems. Maybe you do your patch in an obscure area of the code, and a new developer writes a method that uses the expected behaviour, and then spends a day or so trying to work out why her code isn’t working correctly. Or even worse, somebody decides to write another monkey-patch on the same method, meaning that the behaviour in production becomes a Fun Race Condition That Wakes You Up At 3am depending on which one is executed by Ruby first.

The real answer is Don’t Monkey-Patch, and enforce it with hammers. But sometimes it’s not possible to avoid that monkey. Thankfully, Ruby 2 delivers a way of at least limiting the scope of patches with Refinements.


module WithAMonocle
  refine String do
    def all_is_love
      '❤' * self.length
    end
  end
end

Module#refine takes a class and a block, and in that block, you can extend or redefine to your heart’s content. But:


pry(main)> 'hello’.all_is_love                                             
NoMethodError: undefined method `all_is_love’ 
for "hello":String

Refinements need to be specifically activated with the using keyword:


using WithAMonocle
puts ‘hello’.all_is_love
=> "❤❤❤❤❤”

Okay, so far, much the same as normal monkey-patching. But the magic is that the patch only exists in that scope. So if we embed them in a Class, the refinement only exists within that class. For example:


class SplendidMonkey
  using WithAMonocle
  puts 'fff’.all_is_love
end

❤❤❤
=> nil

class UncouthMonkey
  puts 'fff’.all_is_love
end

=> NoMethodError: undefined method `all_is_love’ 
for "fff":String

The monkey-patch is restricted to the class where it is activated. As you can imagine, this is all sorts of useful - not only do you not pollute the global scope with your redefinitions or extensions, but you also make it explicit that you’re using that particular patch (and also providing a giant big clue where the patch is defined).

So, still, don’t go crazy with your monkey-patching, but, if you have to use them (and you’re running on a current Ruby 2.1.x version), consider using refinements as a way to limit their problematic features…

(however, do be aware that there are a few odd things that may bite you if you’re not paying attention. In particular:


module WithAShortMonocle
  refine String do
    HEART_LENGTH = 1
    def all_is_love
      '❤' * HEART_LENGTH
    end
  end
end

Constants and class variables within a refinement belong to the module, not the class being refined:


pry(main)> String::HEART_LENGTH
NameError: uninitialized constant 
String::HEART_LENGTH
pry(main)> WithAShortMonocle::HEART_LENGTH
=> 1

So be aware of that when adding your refinements)

Sick Raleigh

(raleigh, sick)
()

This week I seem to have spent a lot of time ill, and a lot of time in Raleigh. Good to see the Reverbnation team again during All Things Open, though it would have been better if I hadn’t been feeling quite so ill.

In other discoveries this week: pickling red onions in orange and lime juice is actually quite tasty…

allo darlin’ - the chocolate box

(chocolate, Chocolate, CHOCOLATE, it never ends)
()

Some of you may remember that I once sent Los Campesinos! an anonymous box of sweets and chocolates. Thankfully, they never filed for a restraining order. So when I discovered that Allo Darlin’ were coming back to Chapel Hill on their tour for We Come From The Same Place, it was suggested by a friend that I do something similar, except this time, email them ahead of time so it doesn’t seem quite so creepy.

Remember, it was all Tammy’s fault. Nothing to do with me.

Tammy did indeed said the email, and the response was pretty positive, even going as far to ask one of their friends what chocolates we should make, who came back with the idea of:

a soft sea-salt caramel encased in milk chocolate, then covered in dark chocolate, with an extra dusting of sea-salt on top

I think I read that email three times and then bashed my head on the table. Then I composed myself. After all, it only involved tempering two different types of chocolate, casting them one after the other in a mold, making sure not to melt the already-cast chocolate, then piping in a soft-set caramel that has to cool down from 117˚C to 30˚C so as not to melt the milk chocolate and hope that it’s still pipe-able at that temperature…and then…

muffled cries and groans

Obviously, given that start, I did the only thing a sane person would: I decided that I needed to make a 4-piece set, which meant I needed to come up with three other chocolates. Naturally.

It did give me a chance to break in the new chocolate room, though.

Chalkboard

From the board, I had my four chocolates, which we matched to Allo Darlin’ lyrics (it seemed appropriate):

  • Heartbeat Chilli — a dark chocolate ganache with infused spices to try and replicate Locopops’ Mexican Chocolate locopop (turns out a hint of lime really helps). Cast in a fancy heart mold.

Hearts!

  • Capricornia — goat cheese ganache (Capricorn, see, get it? Get it? GET IT? Ahahaha!). Some people think this is a bit odd, but there’s plenty of lemon and it ends up tasting like cheesecake. Cast in my fancy hemisphere molds.

chocolates in a half-shell!

  • Allo Darlin’ — it seemed appropriate to name the dark / milk / caramel creation after the band. These ended up just being time-consuming than too difficult, though there was a moment when I was about to turn the mold upside-down to empty out the milk chocolate internal layer when I suddenly realized that the dark chocolate had probably pulled away during tempering…which meant I was about to drop 40 dark chocolate shells into the temperer and then shout a lot. Thankfully, I managed to catch myself before I ruined a lot of chocolate. Then I painted the tops with 83% Valrhona, so there was actually three different types of chocolate in the result.

And, yes, as it turned out, the band’s friend was really onto something with the double-hull. The mixture of the different chocolates, the salt and the caramel was pretty delicious.

Piping in the caramel

  • The Shattered Dreams of England — most pretentious name for a chocolate, ever! I was all proud of myself for coming up with this one: a mandarin pâte de fruit in the top with aerated (aero) chocolate filling up the rest of the mold. I remained proud right up until I was idly browsing through my copy of The Fat Duck Cookbook and found exactly the same thing staring back at me. Oops. Anyway, it tasted like a very fancy Jaffa Cake.

Putting the pâte de fruit in the mold

Spraying aero chocolate everywhere

The chocolate box

The weekend thus lost to chocolate, all that remained was to go to Chapel Hill and hand-deliver the chocolates to a rather excited band. At this point, I would link to a photo of handing them over to the happy band…but I completely forgot to take any pictures. However, they did take some of the chocolates:

Loading

Incredible. Handmade chocolate delivery for us in Chapel Hill, NC!

View on Instagram

The slight downside of arriving at a concert two hours before the doors opening is that you desperately try to not come off as a crazy stalker…which gets harder when you keep bumping into band members as you’re walking around Franklin Street. It wasn’t done on purpose, honest! (but they were all friendly and amazing).

And it all ended up with an amazing concert — it was lovely to hear Tallulah live for the first time, and the new album has been playing here in Durham all week…

…but I still can’t look at chocolate yet. Maybe next week.

The Week Looms Ahead

(there’s never enough time)
()

Internet, I do hope you’ll forgive me, or at least reproach me too much for the detail that I’ve been in my pyjamas since 18:30. A day of travelling, or at least a day of last-minute scurrying trying to leave the house in a decent state before getting to the airport and then sitting down a lot. It’s more tiring than you’d think. Honest.

And so back at the centre of bustling activity that is Winter Street in Waltham. There may have been some birds flying overhead at one point. And they’ve now completely torn down the American Brutalist buildings across the road. Heathens.

It will be another quiet week, I imagine, though things will ramp up at the weekend with a couple of days of intense chocolate making, including one chocolate that I’m calling ‘The Shattered Dreams of England’. Yes.

(incidentally, that is a big clue as to what the occasion the chocolates are for, but there’s about three potential people reading that might get the reference)

Right, another week of developing in the office awaits. Meanwhile, I’m going to spend the evenings watching Dennis Potter films. I know how to put on a good time, you see.

Chocolate Room 2.0

(this is, fake, diy)
()

Do I get to call myself an adult now? Carpet ripped from the floorboards, new flooring cut to fit and placed, holes patched in the wall, chalkboard paint applied, and a new layout for what hopefully will be some amazing chocolate adventures. With a special set being made for Tammy, as it would never have happened without her dropping by…

Stripping carpet

so much carpet and tile…

Adding the underlay insulation

New floor!

More space, more chocolates!

buy my books
Instant Zepto.js
Scaling Node.JS (coming soon)