Yukihiro Matsumoto wrote:
#method_missing is and will be called when you invoke private methods
with the receiver specified.
Great! Thank you..
I have come up with the following implementation as a more flexible
solution to BlankSlate. I called it InterfaceFilter for lack of a
better name. I see one prbolem though. It cannot react dynmically when
a new method is added to an ancestor. While, it would make sense if
#method_added triggered the same callback in effected sublasses, I
suppose that's too much overhead. Still, is their anyway to achieve
dynamic behavior here?
T.
module InterfaceFilter
ESSENTIAL = [ 'funcall', 'send', 'object_id', 'object_class'
'equal?', '==', 'dup', 'clone' ]
SECONDARY = [ 'class', 'respond_to?', 'inspect', 'hash' ]
OPERATOR = [ /^\W$/ ]
SHADOW = [ /^__/ ]
QUERY = [ /\?$/ ]
INSTANCE = [ /^instance_/ ]
DEFAULT = ESSENTIAL | SECONDARY | SHADOW | OPERATOR | QUERY
···
#
def self.included( base )
base.const_set( 'InterfaceFilter', self )
end
#
def self.( *patterns )
cls = self.dup
cls.preserve_features( patterns, public_instance_methods(true) )
cls
end
#
def self.preserve_features( patterns, methods=nil )
patterns.flatten!
methods ||= Kernel.public_instance_methods
methods.each do |m|
case m
when *patterns
public m
else
private m
end
end
end
preserve_features( DEFAULT )
end
#= begin test
class X
include InterfaceFilter[ InterfaceFilter::ESSENTIAL ]
end
x = X.new
p X.ancestors
p x.class
p x.instance_variables
#=end