asemanfar - a blog about programming

Monkey Patching Galore

March 03, 2008

Here is some code I just threw together for fun, I don't actually use it. Some would call this monkey patching.

   1  class Symbol
   2    def to_proc
   3      Proc.new { |*args| args.shift.__send__(self, *args) } 
   4    end
   5  end
   6  
   7  class Array
   8    def all?(*args, &block)
   9      !!self.each { |e| return false unless block.call(e, *args) } 
  10    end
  11    
  12    def array_of?(klass)
  13      self.all?(klass, &:is_a?)
  14    end
  15  end
  16  
  17  
  18  puts ["Will", "this", "work?"].array_of?(String) # => true
  19  
  20  puts ["But", "this", 1, "will", "be false"].array_of?(String) # => false
  21  
  22  puts ["But", "wait", "this still works"].all?(&:to_s) # => true

Alright, so I used the well-known Symbol#to_proc, redefined Array#all? and added a method Array#array_of?. But look, Array#all? still works when you try to use it the original way. If you don't like my code, don't use it. I wouldn't.

What would have been a non-monkey patch way of doing this?

   1  class SingleTypedArray < Array
   2    def array_of?(klass)
   3      !!self.each { |e| return false unless e.is_a?(klass) }
   4    end
   5  end

But hey, that's gross. I lose my ability to do [elem1, elem2], I have to do SingleTypedArray.new(elem1, elem2, ...).

I've run into a lot of Rails plugins that add functionality to existing classes, such as ActiveRecord and some of them do it in an obtrusive way, so I simply choose not to use that plugin. You are not required to use a plugin, library, or gem that does something you want if it does it grossly. There are a lot of plugins and gems out there, but a lot of them suck and are poorly designed. Pick and choose the ones that do it right.

Basically: it's not Ruby, it's some programmers.

"Guns don't kill people. People kill people."

Comments

posted by Rob Olson on 03/03/08 12:34 PM PST

Or more appropriate would be,

"Ruby doesn't kill programming. People kill programming."

posted by Avdi on 03/25/08 10:50 PM PDT

Basically: it's not Ruby, it's some programmers.

Which is precisely what I said.

You are not required to use a plugin, library, or gem that does something you want if it does it grossly. There are a lot of plugins and gems out there, but a lot of them suck and are poorly designed. Pick and choose the ones that do it right.

This is very easy to say when you are just one programmer working on personal projects. When you have are working on a tens or hundreds of kloc project which has been under development for years by dozens of developers, you can't always pick and choose the libraries which, for whatever legacy reasons, the project now depends on.
The real drift of my posts, though, is that a lot of the dynamic class modification that goes on in Ruby (and especially Rails) libraries is not only unnecessary, but actually more complicated and harder to write than the alternative techniques!

I've never said anything against Ruby. I'm happy with Ruby the way it is. What's wrong with introducing "some programmers" to alternative ways of solving problems? When you work on a large project with a tight schedule, and find yourself having to waste precious time re-implementing or patching otherwise useful libraries because they were implemented in an unsustainable way, helping people avoid those mistakes in the first place starts to seem more and more important.


Leave a Comment