Enumerable::Proxy

Published September 23, 2009 in Ruby

I’ve been playing with a pattern that replaces the Rails Symbol#to_proc pattern. Instead of doing

@my_objects.each(&:save!)

You would do

@my_objects.proxy(:each).save!


The advantage to this pattern is that it also allows passing in arguments to the proxied method, as in

%w(a b c).proxy(:all?).respond_to? :downcase #=> true
[1, 2, 3].proxy(:map) * 10 #=> [10, 20, 30]

I’ve been using this pattern and am quite happy with it, so I thought I’d publish it. Here’s the monkeypatch:

module Enumerable
  def proxy(method)
    Proxy.new method, self
  end
  
  class Proxy
    instance_methods.each { |m| undef_method m unless m =~ /^__/ }
    
    def initialize(method, enumerable)
      @method, @enumerable = method, enumerable
    end
    
    def method_missing(method, *args)
      @enumerable.send(@method) {|a| a.send method, *args}
    end
  end
end

I’d love feedback on the interface. Is there a shorter, but still clear replacement for “proxy”? Would it totally flip people out if #each and #map returned an Enumerable::Proxy if called with no arguments? That would let you do %w(a b c).each.to_s, which looks pretty cool.

Edit: I implemented the above suggestion. More details are here