DZone Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

Snippets has posted 5883 posts at DZone. View Full User Profile

Flexible Include: Allows Rename Or Exclude Specific Methods.

12.06.2005
| 1737 views |
  • submit to reddit
        From http://eigenclass.org/hiki.rb?Rename+and+reject+methods+from+included+modules:

Daniel Berger blogged about how to make 'include' a little more flexible by allowing to rename or exclude specific methods.

He proposed the following syntax: 
module TFoo
    def method_a
       "hello"
    end
    def method_b
       "world"
    end
end

module TBar
    def method_a
       "goodbye"
    end
    def method_b
       "cruel world"
    end
    def method_y
       "huh?"
    end
end

class MyKlass
    include TFoo,
      :alias   => {:method_a, :method_z},
      :exclude => :method_b

    include TBar
end

m = MyKlass.new
m.method_a                                         # => "goodbye"
m.method_b                                         # => "cruel world"
m.method_y                                         # => "huh?"
m.method_z                                         # => "hello"


Mauricio's implementation follows:

This definition of Class#include should be a fairly safe replacement for the default one since I'm not raising an exception when there's a nameclash (which I rather feel is a bad idea, but I haven't given this much thought), but maybe it could make sense to create a new method with those semantics.

The code:

include_and_rename.rb 
class Class
  old_include = instance_method(:include)
  define_method(:include) do |*args|
    default = {:alias => {}, :exclude => []}
    hash_arg = (Hash === args.last) ? default.update(args.pop) : default
    m = Module.new
    args.each{|mod| m.module_eval{ include mod } }
    #                            ^^^^^^^^^^^^^^^
    # check for "method shadowing" here and raise an exception or
    # something if you feel like it
    hash_arg[:alias].each_pair do |old, new|
      m.module_eval{ alias_method(new, old); undef_method(old) }
    end
    excluded = (Array === hash_arg[:exclude]) ? hash_arg[:exclude] : [hash_arg[:exclude]]
    # [*hash_arg[:exclude]] won't work on 1.9 cause there's no Object#to_a
    excluded.each{|meth| m.module_eval { undef_method(meth) } }
    old_include.bind(self).call(m)
  end
end

    

Comments

Snippets Manager replied on Mon, 2012/05/07 - 2:17pm

Look to RedHanded for more goodness. http://redhanded.hobix.com/inspect/mixinsButWithTablespoons.html