Skip to content

Instantly share code, notes, and snippets.

@trans
Created June 24, 2009 14:09
Show Gist options
  • Select an option

  • Save trans/135295 to your computer and use it in GitHub Desktop.

Select an option

Save trans/135295 to your computer and use it in GitHub Desktop.
Dynamically Privatize Methods
# Method Filter - Dynamically Privatize New Methods
#
# Since Ruby is very dynamic, methods added to Object will show
# up in the list of available methods of subclasses. If we are trying to privatize
# methods to get them out of the way for method_missing, then this could pose
# a problem. We handle this by defining hooks in Object, Kernel and Module
# that will hide any method so defined automatically.
#
# This is rather useless now that Ruby 1.9 provides BasicObject.
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
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment