# Module#private\_filter: critique of dynamic method visibility

**URL:** <https://www.ruby-forum.com/t/module-private-filter-critique-of-dynamic-method-visibility/98569>\
**Category:** Ruby\
**Created:** [July 16, 2006, 4:00am UTC](https://www.ruby-forum.com/t/module-private-filter-critique-of-dynamic-method-visibility/98569 "2006-07-16T04:00:36Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [July 16, 2006, 4:00am UTC](https://www.ruby-forum.com/t/module-private-filter-critique-of-dynamic-method-visibility/98569/1 "2006-07-16T04:00:36Z")

</div>

The following fancy function does some pretty delicate handling of  
method visibility. And as such I would really like to get some extra  
eyes on it. I wonder, is it worth it? Can it be improved? Is there a  
whole better way of dealing? Etc.

The idea is to be able to define a pattern of methods that will be  
granted public visibility, while all others are kept private, even when  
new methods are added dynamically to Kernel or Object.

I’m currently using it like so:

class OpenObject \< Hash  
private\_filter //  
…  
def method\_missing(sym,\*args)  
…  
end  
end

Thanks,  
T.

class Module

STANDARD\_FILTER =  
/(?$|^(\_\_|object\_|instance\_)|^(send|inspect|dup|clone|null|\W+)$)/

@@private\_filters = {}

def private\_filter( \*filter )  
return @@private\_filters[self] if filter.empty?  
filter.collect! do |f|  
if f == //  
STANDARD\_FILTER  
elsif Regexp === f  
f  
else  
f.to\_s  
end  
end  
@@private\_filters[self] = filter  
public\_instance\_methods.each do |name|  
case name.to\_s  
when \*filter  
#puts “public #{name}”  
else  
#puts “private #{name}”  
private name  
end  
end  
filter  
end

# 

# 

def self.filter(name)  
@@private\_filters.each do |base, filter|  
case name.to\_s  
when \*base.private\_filter  
else  
base.send(:private,name)  
end  
end  
end

end

# Since Ruby is very dynamic, methods added to the ancestors of a class

# after private\_filter is defined will show up in the list of public

methods.

# We handle this by defining hooks in Object, Kernel and Module that

will

# hide any defined.

module Kernel  
class \<\< self  
madded = method(:method\_added)  
define\_method(:method\_added) do |name|  
r = madded.call(name)  
return r if self != Kernel  
Module.filter(name)  
r  
end  
end  
end

# See Kernel callback.

class Object  
class \<\< self  
madded = method(:method\_added)  
define\_method(:method\_added) do |name|  
r = madded.call(name)  
return r if self != Object  
Module.filter(name)  
r  
end  
end  
end

# \_\_\_\_\_ \_

# |\_ _|_\_ \_\__| |_

# | |/ \_ / \_\_| \_\_|

# | | _/\_ \ |_

# |_|\_ **||** _/\_\_|

# 

=begin test

require ‘test/unit’

class TestMethodFilter1 \< Test::Unit::TestCase

```
class X
  private_filter //
  def foo ; end
  def method_missing(name,*args)
    name
  end
end

def test_1_01
  x = X.new
  assert_equal( :class, x.class )
end

def test_1_02
  x = X.new
  assert_not_equal( :object_id, x.object_id )
end

def test_1_02
  x = X.new
  assert( x.respond_to?(:foo) )
end

```

end

=end
