Over a million developers have joined DZone.

Flexible Include: Allows Rename Or Exclude Specific Methods.

·
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

Topics:

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}