This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: The Ruby Facade
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
Facade patterns, that is. I usually don't get into design patterns. Or rather, I'm probably using design patterns with Ruby on a daily basis, but they're so natural in Ruby I probably don't even realize that I'm doing it. No gagging.
Recently, however, I had a scenario where I had a subclass of String. I wanted to implement many of the File class methods as instance methods of my custom class. The long way looks like this:
class Foo < String
def basename
File.basename(self)
end
def dirname
File.dirname(self)
end
end
Easy enough for a few methods, but this gets ugly fast when many methods are involved. There has to be a shortcut, right? This is where the facade pattern comes in. Instead of doing that, let's use the "facade" module:
require "facade"
class Foo < String
extend Facade
facade File, :basename, :dirname
end
f = Foo.new("/home/djberge")
puts f.basename # 'djberge'
puts f.dirname # '/home'
What if I want every File class method included?
class Foo < String
extend Facade
facade File, File.methods
end
Cool, eh?
Here's a "facade" module (as yet unpublished). Note that it doesn't replace existing methods, which is intentional. I thought that would get too confusing. The begin/rescue clause is to allow methods that don't take any arguments, e.g. Dir.getwd.
def facade(klass, *methods)
methods.flatten! if methods.respond_to?(:flatten!)
methods = methods - self.methods
methods.each{ |method|
define_method(method){ ||
begin
klass.send(method, self)
rescue ArgumentError
klass.send(method)
end
}
}
end