This post originated from an RSS feed registered with Ruby Buzz
by Daniel Berger.
Original Post: Tricks with modules
Feed Title: Testing 1,2,3...
Feed URL: http://djberg96.livejournal.com/data/rss
Feed Description: A blog on Ruby and other stuff.
As things stand now with Ruby the include directive isn't very flexible:
class Foo
include Bar
end
In the above example, the Foo class mixes in *all* of the methods of the Bar module. On the sydney-devel mailing list someone was trying to arrange things so that he could selectively mixin certain methods from a module. Perl users are used to being able to do this. Here's an example:
use Foo qw/bar baz/;
This would import the functions bar and baz from the package Foo in Perl. Of course, you can selectively export functions in Perl as well, but I digress.
Is this possible in Ruby? It is, though it isn't exactly intuitive since tricks with bind, which is how I thought it would be solved, just don't work. In a nutshell, you create an anonymous module, undef all the unwanted methods from the original module, then call module_eval. Thanks go to Ara Howard for the solution.
As cool as that is, I still have a nagging feeling there's a fundamental design problem with the original poster's approach to whatever problem he's trying to solve. In Ruby, the need to selectively mixin specific methods is so rare, and so un-Ruby-like, that I'm afraid I'm left wondering just what the heck they're doing. The only reason I could see for doing something like that is a scenario where you have multiple modules you want to include which have identical methods. Even then, module functions should solve your problem.
Well, heck, it's a cool little trick anyway, so I'll publish the "use" package sometime this week. It will simply look like this:
module Foo
def bar
"hello"
end
def baz
"world"
end
end
class Zap
use Foo, :bar
end
z = Zap.new
z.bar # "hello"
z.baz # NoMethodError
Oh, quick note - I was going to just redefine include, until I realized that it can take multiple module names! Guess it goes to show you how often I include multiple modules in the same class. ;)