Then I thought why not do something similar in Ruby too? By sheer luck I was just messing around with Module#method_added and it’s dead easy to implement. method_added isn’t documented online but it receives one argument, which is the Symbol corresponding to the new method’s name.
Here’s something I just put together. It’s neither eloquent nor useful but it illustrates the idea.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
class Module @@magic_methods = {} def magic_method(id) id = id.to_sym @@magic_methods[id] = self puts "magic method registered: #{id.inspect} => #{self.inspect}" end def method_added(id) puts "magic method for #{id.inspect}? #{@@magic_methods[id].inspect}" return unless @@magic_methods.has_key?(id) class_eval do include @@magic_methods[id] end end end module Bar magic_method :foo def bar foo << ' bar!' end end class Foo def foo 'foo?' end end foo = Foo.new puts foo.bar |
Then presumably one could code the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
module Enumerable magic_method :each ... end module Comparable magic_method '<=>' ... end class MyClass def each ... end # at this point Module#method_added includes Enumerable in the context of MyClass ... def <=>(other) ... end # at this point Module#method_added includes Comparable in the context of MyClass end |
Is this more difficult than just writing include Enumerable? Maybe.
Would it annoy some programmers? Yes.
Is it still pretty sweet? Hell yes!
