######################################################################
# Jsonify::BlankSlate is based on Jim Weirich's BlankSlate.
#
# Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
# All rights reserved.
#
# BlankSlate provides an abstract base class with no predefined
# methods (except for \_\_send__ and \_\_id__).
# BlankSlate is useful as a base class when writing classes that
# depend upon method_missing (e.g. dynamic proxies).
#
# This Jsonify implementation of BlankSlate is identical; with the
# exception that it does not include the Kernel, Module, and Object
# patches.
#
module Jsonify
class BlankSlate
class << self
# Hide the method named +name+ in the BlankSlate class. Don't
# hide +instance_eval+ or any method beginning with "__".
def hide(name)
if instance_methods.include?(name.to_s) and
name !~ /^(__|instance_eval)/
@hidden_methods ||= {}
@hidden_methods[name.to_sym] = instance_method(name)
undef_method name
end
end
def find_hidden_method(name)
@hidden_methods ||= {}
@hidden_methods[name] || superclass.find_hidden_method(name)
end
# Redefine a previously hidden method so that it may be called on a blank
# slate object.
def reveal(name)
hidden_method = find_hidden_method(name)
fail "Don't know how to reveal method '#{name}'" unless hidden_method
define_method(name, hidden_method)
end
end
instance_methods.each { |m| hide(m) }
end
end
######################################################################
# Since Ruby is very dynamic, methods added to the ancestors of
# BlankSlate after BlankSlate is defined will show up in the
# list of available BlankSlate methods. We handle this by defining a
# hook in the Object and Kernel classes that will hide any method
# defined after BlankSlate has been loaded.
#
# module Kernel
# class << self
# alias_method :blank_slate_method_added, :method_added
#
# # Detect method additions to Kernel and remove them in the
# # BlankSlate class.
# def method_added(name)
# result = blank_slate_method_added(name)
# return result if self != Kernel
# BlankSlate.hide(name)
# result
# end
# end
# end
######################################################################
# Same as above, except in Object.
#
# class Object
# class << self
# alias_method :blank_slate_method_added, :method_added
#
# # Detect method additions to Object and remove them in the
# # BlankSlate class.
# def method_added(name)
# result = blank_slate_method_added(name)
# return result if self != Object
# BlankSlate.hide(name)
# result
# end
#
# def find_hidden_method(name)
# nil
# end
# end
# end
######################################################################
# Also, modules included into Object need to be scanned and have their
# instance methods removed from blank slate. In theory, modules
# included into Kernel would have to be removed as well, but a
# "feature" of Ruby prevents late includes into modules from being
# exposed in the first place.
#
# class Module
# alias blankslate_original_append_features append_features
# def append_features(mod)
# result = blankslate_original_append_features(mod)
# return result if mod != Object
# instance_methods.each do |name|
# BlankSlate.hide(name)
# end
# result
# end
# end