OSDN Git Service

da6034d9c45c859302c43f3f6223d9b6501ee298
[redminele/redminele.git] / ruby / lib / ruby / gems / 1.8 / gems / activesupport-2.3.5 / lib / active_support / vendor / builder-2.1.2 / blankslate.rb
1 #!/usr/bin/env ruby
2 #--
3 # Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
4 # All rights reserved.
5
6 # Permission is granted for use, copying, modification, distribution,
7 # and distribution of modified versions of this work as long as the
8 # above copyright notice is included.
9 #++
10
11 ######################################################################
12 # BlankSlate provides an abstract base class with no predefined
13 # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
14 # BlankSlate is useful as a base class when writing classes that
15 # depend upon <tt>method_missing</tt> (e.g. dynamic proxies).
16 #
17 class BlankSlate
18   class << self
19
20     # Hide the method named +name+ in the BlankSlate class.  Don't
21     # hide +instance_eval+ or any method beginning with "__".
22     def hide(name)
23       if instance_methods.include?(name.to_s) and
24         name !~ /^(__|instance_eval)/
25         @hidden_methods ||= {}
26         @hidden_methods[name.to_sym] = instance_method(name)
27         undef_method name
28       end
29     end
30
31     def find_hidden_method(name)
32       @hidden_methods ||= {}
33       @hidden_methods[name] || superclass.find_hidden_method(name)
34     end
35
36     # Redefine a previously hidden method so that it may be called on a blank
37     # slate object.
38     def reveal(name)
39       bound_method = nil
40       unbound_method = find_hidden_method(name)
41       fail "Don't know how to reveal method '#{name}'" unless unbound_method
42       define_method(name) do |*args|
43         bound_method ||= unbound_method.bind(self)
44         bound_method.call(*args)
45       end
46     end
47   end
48
49   instance_methods.each { |m| hide(m) }
50 end
51
52 ######################################################################
53 # Since Ruby is very dynamic, methods added to the ancestors of
54 # BlankSlate <em>after BlankSlate is defined</em> will show up in the
55 # list of available BlankSlate methods.  We handle this by defining a
56 # hook in the Object and Kernel classes that will hide any method
57 # defined after BlankSlate has been loaded.
58 #
59 module Kernel
60   class << self
61     alias_method :blank_slate_method_added, :method_added
62
63     # Detect method additions to Kernel and remove them in the
64     # BlankSlate class.
65     def method_added(name)
66       result = blank_slate_method_added(name)
67       return result if self != Kernel
68       BlankSlate.hide(name)
69       result
70     end
71   end
72 end
73
74 ######################################################################
75 # Same as above, except in Object.
76 #
77 class Object
78   class << self
79     alias_method :blank_slate_method_added, :method_added
80
81     # Detect method additions to Object and remove them in the
82     # BlankSlate class.
83     def method_added(name)
84       result = blank_slate_method_added(name)
85       return result if self != Object
86       BlankSlate.hide(name)
87       result
88     end
89
90     def find_hidden_method(name)
91       nil
92     end
93   end
94 end
95
96 ######################################################################
97 # Also, modules included into Object need to be scanned and have their
98 # instance methods removed from blank slate.  In theory, modules
99 # included into Kernel would have to be removed as well, but a
100 # "feature" of Ruby prevents late includes into modules from being
101 # exposed in the first place.
102 #
103 class Module
104   alias blankslate_original_append_features append_features
105   def append_features(mod)
106     result = blankslate_original_append_features(mod)
107     return result if mod != Object
108     instance_methods.each do |name|
109       BlankSlate.hide(name)
110     end
111     result
112   end
113 end