Saturday, October 18, 2008

Module#to_proc h0tness

I don't need this right now, so I'm not putting it into any of the codebases I touch. But if I ever do need it, I haven't thought of a reason yet that I shouldn't pull it in.

describe "Module#to_proc" do
  it "provides a proc that mixes the module into the yielded object" do
    # Say you've got some stuff,
    stuff = ["jimmy", "jane",]
    # and you want to have all that stuff extend a certain Module.
    module Fooable
      def foo() "This #{self.class} is fooing"; end
    # stuff.each {|thing| thing.extend Fooable } is just so many
    # characters to type!
    # With a little hackery in Module, you can do this.
    stuff.each &Fooable
    # Now all that stuff will have your module mixed in,
    stuff.each {|thing| thing.should be_a_kind_of(Fooable) }
    # and have interesting new behavior.
    stuff.collect {|o| }.should == [
      "This String is fooing",
      "This String is fooing",
      "This Object is fooing"]

Here's all it takes to make it pass, plus some simple memoization so it's cheaper to call.

class Module
  def to_proc
    @to_proc ||= {|o| o.extend self }