contextr 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +5 -18
- data/License.txt +20 -0
- data/Manifest.txt +15 -19
- data/README.txt +2 -49
- data/Rakefile +55 -88
- data/examples/general.rb +152 -0
- data/examples/ordering.rb +29 -0
- data/lib/contextr.rb +15 -15
- data/lib/contextr/class_methods.rb +90 -0
- data/lib/contextr/core_ext.rb +2 -0
- data/lib/contextr/core_ext/module.rb +18 -0
- data/lib/contextr/core_ext/object.rb +9 -0
- data/lib/contextr/event_machine.rb +71 -0
- data/lib/contextr/layer.rb +57 -381
- data/lib/contextr/modules/mutex_code.rb +22 -0
- data/lib/contextr/modules/unique_id.rb +13 -0
- data/lib/contextr/public_api.rb +58 -0
- data/lib/contextr/version.rb +2 -2
- data/lib/ext/active_support_subset.rb +85 -0
- data/spec/contextr_spec.rb +11 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +1 -1
- data/test/test_contextr.rb +11 -0
- data/website/index.html +23 -101
- data/website/index.txt +27 -95
- data/website/stylesheets/screen.css +9 -0
- data/website/template.rhtml +3 -8
- metadata +21 -26
- data/COPYING.txt +0 -340
- data/LICENSE.txt +0 -57
- data/examples/education.rb +0 -71
- data/examples/fibonacci.rb +0 -124
- data/examples/with_current_context.rb +0 -29
- data/lib/contextr/contextr.rb +0 -160
- data/lib/core_ext/class.rb +0 -29
- data/lib/core_ext/module.rb +0 -62
- data/lib/core_ext/proc.rb +0 -53
- data/lib/ext/method_nature.rb +0 -80
- data/rake/group_spec_task.rb +0 -7
- data/rake/specific_group_spec_task.rb +0 -7
- data/spec/contextr/contextr_api_spec.rb +0 -126
- data/spec/contextr/contextr_class_side_spec.rb +0 -77
- data/spec/contextr/contextr_functional_spec.rb +0 -293
- data/spec/core_ext/module_spec.rb +0 -101
- data/spec/core_ext/proc_spec.rb +0 -61
- data/tasks/annotations.rb +0 -107
- data/test/contextr/test_contextr.rb +0 -7
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../lib/contextr.rb"
|
2
|
+
|
3
|
+
class AnyClass
|
4
|
+
def test
|
5
|
+
puts "base_method"
|
6
|
+
end
|
7
|
+
|
8
|
+
module InnerMethods
|
9
|
+
def test
|
10
|
+
puts "inner_pre"
|
11
|
+
yield(:next)
|
12
|
+
puts "inner_post"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
include InnerMethods => :test
|
16
|
+
|
17
|
+
module OuterMethods
|
18
|
+
def test
|
19
|
+
puts "outer_pre"
|
20
|
+
yield(:next)
|
21
|
+
puts "outer_post"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
include OuterMethods => :test
|
25
|
+
end
|
26
|
+
|
27
|
+
ContextR::with_layer :test do
|
28
|
+
AnyClass.new.test
|
29
|
+
end
|
data/lib/contextr.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
#++
|
4
|
-
unless Object.const_defined? "ContextR"
|
5
|
-
if RUBY_VERSION == "1.9.0"
|
6
|
-
require File.dirname(__FILE__) + '/activesupport/lib/active_support'
|
7
|
-
else
|
8
|
-
require 'rubygems'
|
9
|
-
require 'active_support'
|
10
|
-
end
|
1
|
+
module ContextR
|
2
|
+
end
|
11
3
|
|
12
|
-
|
13
|
-
|
14
|
-
|
4
|
+
# vendor code by rails and Cristian Neukirchen and _why
|
5
|
+
%w{active_support_subset dynamic}.each { |file|
|
6
|
+
require File.dirname(__FILE__) + "/ext/#{file}" }
|
7
|
+
|
8
|
+
# modules that encapsulate certain simple aspects
|
9
|
+
%w{mutex_code unique_id}.each { |file|
|
10
|
+
require File.dirname(__FILE__) + "/contextr/modules/#{file}" }
|
11
|
+
|
12
|
+
# the basic library code
|
13
|
+
%w{public_api class_methods layer
|
14
|
+
event_machine core_ext version}.each { | file |
|
15
|
+
require File.dirname(__FILE__) + "/contextr/#{file}" }
|
15
16
|
|
16
|
-
end
|
17
17
|
unless Dynamic.variables.include?( :layers )
|
18
|
-
Dynamic.variable( :layers => [
|
18
|
+
Dynamic.variable( :layers => [] )
|
19
19
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module ContextR
|
2
|
+
module ClassMethods
|
3
|
+
def const_missing(const_name)
|
4
|
+
if const_name.to_s =~ /.*Layer$/
|
5
|
+
self.const_set(const_name, Class.new(ContextR::Layer))
|
6
|
+
else
|
7
|
+
super
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def stored_core_methods
|
12
|
+
@stored_core_methods ||= Hash.new do | hash, key |
|
13
|
+
hash[key] = Hash.new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def symbol_by_layer(lay)
|
18
|
+
lay.to_s.gsub( /^ContextR::(.*)Layer$/, '\1' ).underscore
|
19
|
+
end
|
20
|
+
|
21
|
+
def layer_by_symbol(sym)
|
22
|
+
"ContextR::#{sym.to_s.camelize}Layer".constantize
|
23
|
+
end
|
24
|
+
|
25
|
+
def call_methods_stack(stack, receiver, method_name, arguments, block)
|
26
|
+
if stack.size == 1
|
27
|
+
stack.pop.call(*arguments, &block)
|
28
|
+
else
|
29
|
+
stack.pop.send(method_name, *arguments) do | action, *rest_args |
|
30
|
+
case action
|
31
|
+
when :receiver
|
32
|
+
receiver
|
33
|
+
when :block
|
34
|
+
block.call(*rest_args)
|
35
|
+
when :next
|
36
|
+
call_methods_stack(stack, receiver, method_name, rest_args, block)
|
37
|
+
else
|
38
|
+
raise ArgumentError.new("Use only :receiver, :block or :next " +
|
39
|
+
"as first argument.")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def on_core_method_called(receiver, contextified_class,
|
46
|
+
method_name, arguments, block)
|
47
|
+
proxies = []
|
48
|
+
layers.each do |layer|
|
49
|
+
proxies += layer.context_proxies(contextified_class, method_name)
|
50
|
+
end.compact
|
51
|
+
|
52
|
+
proxies << core_proxy(receiver, contextified_class, method_name)
|
53
|
+
call_methods_stack(proxies.reverse, receiver,
|
54
|
+
method_name, arguments, block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def core_proxy(receiver, contextified_class, method_name)
|
58
|
+
ContextR::stored_core_methods[contextified_class][
|
59
|
+
method_name][:code].bind(receiver)
|
60
|
+
end
|
61
|
+
|
62
|
+
def observe_core_method(klass, method_name, version)
|
63
|
+
only_once do
|
64
|
+
klass.class_eval(%Q{
|
65
|
+
def #{method_name}(*arguments, &block)
|
66
|
+
ContextR::on_core_method_called(
|
67
|
+
self,
|
68
|
+
ObjectSpace._id2ref(#{klass.object_id}),
|
69
|
+
:#{method_name},
|
70
|
+
arguments, block)
|
71
|
+
end
|
72
|
+
}, __FILE__, __LINE__) if save_core_method(klass, method_name, version)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def save_core_method(klass, method_name, version)
|
77
|
+
if !meta_method?(method_name) and
|
78
|
+
(!stored_core_methods[klass].include?(method_name) or
|
79
|
+
stored_core_methods[klass][method_name][:version] < version)
|
80
|
+
stored_core_methods[klass][method_name] =
|
81
|
+
{ :version => version, :code => klass.instance_method(method_name) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def meta_method?(method_name)
|
86
|
+
method_name.to_s =~ /method_added(_with(out)?_contextr_listener)?/
|
87
|
+
end
|
88
|
+
end
|
89
|
+
self.extend(ClassMethods)
|
90
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Module
|
2
|
+
alias_method :include_without_layers, :include
|
3
|
+
def include_with_layers(associations)
|
4
|
+
if associations.delete(:class_side)
|
5
|
+
klass = class << self; self; end
|
6
|
+
else
|
7
|
+
klass = self
|
8
|
+
end
|
9
|
+
associations.each do | modul, layer |
|
10
|
+
ContextR::layer_by_symbol(layer).add_method_collection(klass, modul)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def include(*args)
|
15
|
+
args.first.is_a?(Module) ? include_without_layers(*args) :
|
16
|
+
include_with_layers(*args)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module ContextR
|
2
|
+
class EventMachine
|
3
|
+
module ClassMethods
|
4
|
+
include UniqueId
|
5
|
+
|
6
|
+
def listeners
|
7
|
+
@listeners ||= { :method_added => {} }
|
8
|
+
end
|
9
|
+
|
10
|
+
def register(listener, callback, options)
|
11
|
+
observed = check_options_hash(options)
|
12
|
+
register_observers_on_demand(observed)
|
13
|
+
self.listeners[observed[:event]][observed[:module]][listener] = callback
|
14
|
+
end
|
15
|
+
|
16
|
+
def unregister(listener, *cumulated_options)
|
17
|
+
observed = check_options_hash(cumulated_options.last)
|
18
|
+
self.listeners[observed[:event]][observed[:module]].delete(listener)
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_method_added(modul, name)
|
22
|
+
version = self.new_unique_id
|
23
|
+
self.listeners[:method_added][modul].each do | listener, method_name |
|
24
|
+
listener.send( method_name, modul, name, version )
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_options_hash(options)
|
29
|
+
observed = {}
|
30
|
+
observed[:event] = options[:on_event]
|
31
|
+
observed[:module] = options[:in_class] || options[:in_module]
|
32
|
+
[:event, :module].each do |key|
|
33
|
+
unless observed[key]
|
34
|
+
raise ArgumentError.new("Missing Argument in options Hash")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
unless self.listeners.keys.include?(observed[:event])
|
38
|
+
raise ArgumentError.new("Unknown event `#{observed[:event]}`. " +
|
39
|
+
"Please use one of these: #{self.listeners.keys.join(', ')}")
|
40
|
+
end
|
41
|
+
observed
|
42
|
+
end
|
43
|
+
|
44
|
+
def register_observers_on_demand(observed)
|
45
|
+
unless self.listeners[observed[:event]].include?(observed[:module])
|
46
|
+
self.listeners[observed[:event]][observed[:module]] = {}
|
47
|
+
case observed[:event]
|
48
|
+
when :method_added
|
49
|
+
observe_method_added(observed[:module])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def observe_method_added(modul)
|
55
|
+
modul.class_eval(%Q{
|
56
|
+
def self.method_added_with_contextr_listener(name)
|
57
|
+
ContextR::EventMachine::on_method_added(self, name)
|
58
|
+
method_added_without_contextr_listener(name)
|
59
|
+
end
|
60
|
+
unless self.methods.include? "method_added"
|
61
|
+
def self.method_added(name); end
|
62
|
+
end
|
63
|
+
class << self
|
64
|
+
alias_method_chain(:method_added, :contextr_listener)
|
65
|
+
end
|
66
|
+
}, __FILE__, __LINE__)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
self.extend(ClassMethods)
|
70
|
+
end
|
71
|
+
end
|
data/lib/contextr/layer.rb
CHANGED
@@ -1,410 +1,86 @@
|
|
1
1
|
module ContextR
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
# MethodNature to manipulate arguments or return values.
|
7
|
-
#
|
8
|
-
# class Foo
|
9
|
-
# layer :any
|
10
|
-
#
|
11
|
-
# def bar
|
12
|
-
# "bar"
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# any.pre :bar do | n |
|
16
|
-
# logger.info "Foo#bar called"
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
class LayerInClass
|
20
|
-
attr_accessor :contextualized_class, :layer # :nodoc:
|
21
|
-
|
22
|
-
def initialize( contextualized_class, layer ) # :nodoc:
|
23
|
-
self.contextualized_class = contextualized_class
|
24
|
-
self.layer = layer
|
25
|
-
end
|
26
|
-
|
27
|
-
# Adds a pre-wrapper to a single method.
|
28
|
-
#
|
29
|
-
# :call-seq:
|
30
|
-
# pre( method_name ) { | method_nature | ... }
|
31
|
-
#
|
32
|
-
def pre( method_name, &block )
|
33
|
-
layer.methods_of( self.contextualized_class )[method_name].pres <<
|
34
|
-
block.to_unbound_method( self.contextualized_class )
|
35
|
-
nil
|
36
|
-
end
|
37
|
-
|
38
|
-
# Adds a post-wrapper to a single method
|
39
|
-
#
|
40
|
-
# :call-seq:
|
41
|
-
# post( method_name ) { | method_nature | ... }
|
42
|
-
#
|
43
|
-
def post( method_name, &block )
|
44
|
-
layer.methods_of( self.contextualized_class )[method_name].posts <<
|
45
|
-
block.to_unbound_method( self.contextualized_class )
|
46
|
-
nil
|
47
|
-
end
|
48
|
-
|
49
|
-
# Adds an around-wrapper to a single method
|
50
|
-
#
|
51
|
-
# :call-seq:
|
52
|
-
# around( method_name ) { | method_nature | ... }
|
53
|
-
#
|
54
|
-
def around( method_name, &block )
|
55
|
-
layer.methods_of( self.contextualized_class )[method_name].arounds <<
|
56
|
-
block.to_unbound_method( self.contextualized_class )
|
57
|
-
nil
|
58
|
-
end
|
59
|
-
|
60
|
-
alias :wrap :around
|
61
|
-
end
|
62
|
-
|
63
|
-
class Layer # :nodoc:
|
64
|
-
# its role as base instance of all layers
|
65
|
-
class << self
|
66
|
-
attr_accessor_with_default_setter :base_layers, :combined_layers do
|
67
|
-
Hash.new
|
2
|
+
class Layer
|
3
|
+
module ClassMethods
|
4
|
+
def definitions
|
5
|
+
@definitions ||= {}
|
68
6
|
end
|
69
|
-
|
70
|
-
|
71
|
-
@core_methods ||= Hash.new do | hash, extended_class |
|
72
|
-
add_redefine_callback( extended_class )
|
73
|
-
hash[extended_class] = Hash.new do | class_hash, method_name |
|
74
|
-
um = extended_class.instance_method( method_name )
|
75
|
-
replace_core_method( extended_class, method_name )
|
76
|
-
class_hash[method_name] = um
|
77
|
-
end
|
78
|
-
end
|
7
|
+
def proxies
|
8
|
+
@proxies ||= {}
|
79
9
|
end
|
80
10
|
|
81
|
-
def
|
82
|
-
|
83
|
-
|
11
|
+
def add_method_collection(contextified_class, methods_module)
|
12
|
+
definitions[contextified_class] ||= []
|
13
|
+
definitions[contextified_class] |= [methods_module]
|
14
|
+
(methods_module.instance_methods &
|
15
|
+
contextified_class.instance_methods).each do | method_name |
|
16
|
+
replace_core_method(contextified_class, method_name, 0)
|
84
17
|
end
|
18
|
+
register_callbacks(contextified_class, methods_module)
|
85
19
|
end
|
86
20
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
layer + akku
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
protected
|
96
|
-
def replace_core_method( extended_class, method_name )
|
97
|
-
num_of_args = extended_class.instance_method( method_name ).arity
|
98
|
-
arg_signature = case num_of_args <=> 0
|
99
|
-
when 0
|
100
|
-
""
|
101
|
-
when 1
|
102
|
-
"%s" % Array.new( num_of_args ) { |i| "arg%d" % i }.join( ", " )
|
103
|
-
else
|
104
|
-
"*arguments"
|
105
|
-
end
|
106
|
-
arg_call = arg_signature.empty? ? "" : ", " + arg_signature
|
107
|
-
|
108
|
-
extended_class.class_eval( %Q{
|
109
|
-
remove_method :#{method_name}
|
110
|
-
def #{method_name} #{arg_signature}
|
111
|
-
ContextR::current_layer.extended( self ).send(
|
112
|
-
:#{method_name}#{arg_call} )
|
113
|
-
end
|
114
|
-
}, __FILE__, __LINE__ )
|
115
|
-
end
|
116
|
-
|
117
|
-
def add_redefine_callback( extended_class )
|
118
|
-
(class << extended_class; self; end).instance_eval do
|
119
|
-
define_method( :method_added ) do | method_name |
|
120
|
-
if ContextR::Layer.core_methods[extended_class].
|
121
|
-
include?( method_name )
|
122
|
-
warn( caller.first + " : ContextR - Redefining already wrapped methods is not supported yet. Your changes _may_ have no effect." )
|
123
|
-
end
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
class Layer # :nodoc:
|
131
|
-
# its role as base class for all other layers
|
132
|
-
class << self
|
133
|
-
attr_accessor_with_default_setter :extended_classes do
|
134
|
-
Hash.new do | classes, extended_class |
|
135
|
-
classes[extended_class] = Hash.new do | hash, key |
|
136
|
-
hash[key.to_sym] = ContextualizedMethod.new(
|
137
|
-
ContextR::Layer.core_methods[ extended_class ][ key.to_sym ] )
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
attr_accessor :extended_objects
|
142
|
-
|
143
|
-
def methods_of( extended_class )
|
144
|
-
self.extended_classes[extended_class]
|
145
|
-
end
|
146
|
-
|
147
|
-
def extended( object )
|
148
|
-
self.extended_objects ||= Hash.new do | cache, object |
|
149
|
-
object_class = if object.kind_of? Class
|
150
|
-
(class << object; self; end)
|
151
|
-
else
|
152
|
-
object.class
|
21
|
+
def methods_modules_containing_method(contextified_class, method_name)
|
22
|
+
if definitions.include?(contextified_class)
|
23
|
+
definitions[contextified_class].select do | methods_module |
|
24
|
+
methods_module.instance_methods.include?(method_name.to_s)
|
153
25
|
end
|
154
|
-
cache[ object ] =
|
155
|
-
ExtendedObject.new( object, self.methods_of( object_class ) )
|
156
|
-
end
|
157
|
-
self.extended_objects[object]
|
158
|
-
end
|
159
|
-
|
160
|
-
def + other_layer
|
161
|
-
if other_layer.nil?
|
162
|
-
self
|
163
26
|
else
|
164
|
-
|
165
|
-
combined_layer.extended_classes = self.merge_extended_classes_with(
|
166
|
-
other_layer.extended_classes )
|
167
|
-
combined_layer
|
27
|
+
[]
|
168
28
|
end
|
169
29
|
end
|
170
30
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
my_cm + other_cm
|
177
|
-
end
|
178
|
-
end
|
31
|
+
def context_proxies(contextified_class, method_name)
|
32
|
+
methods_modules_containing_method(contextified_class, method_name).
|
33
|
+
collect do | methods_module |
|
34
|
+
context_proxy_for_module(methods_module)
|
35
|
+
end.reverse
|
179
36
|
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
class ExtendedObject # :nodoc:
|
184
|
-
attr_accessor :proxied_object
|
185
|
-
attr_accessor :extended_methods
|
186
|
-
attr_accessor :behaviours
|
187
|
-
|
188
|
-
def initialize( proxied_object, extended_methods )
|
189
|
-
self.proxied_object = proxied_object
|
190
|
-
self.extended_methods = extended_methods
|
191
|
-
self.behaviours = {}
|
192
|
-
end
|
193
37
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
class ContextualizedMethod # :nodoc:
|
202
|
-
attr_accessor :core
|
203
|
-
attr_accessor :behaviour_cache
|
204
|
-
|
205
|
-
attr_accessor_with_default_setter :pres, :posts, :arounds do
|
206
|
-
Array.new
|
207
|
-
end
|
208
|
-
|
209
|
-
def initialize( unbound_core_method )
|
210
|
-
self.core = unbound_core_method
|
211
|
-
self.behaviour_cache = {}
|
212
|
-
end
|
213
|
-
|
214
|
-
def + other_cm
|
215
|
-
new_cm = ContextualizedMethod.new( self.core )
|
216
|
-
new_cm.pres = self.pres + other_cm.pres
|
217
|
-
new_cm.posts = self.posts + other_cm.posts
|
218
|
-
new_cm.arounds = self.arounds + other_cm.arounds
|
219
|
-
new_cm
|
220
|
-
end
|
221
|
-
|
222
|
-
def behaviour( instance )
|
223
|
-
self.behaviour_cache[instance] ||=
|
224
|
-
self.send( self.behaviour_name, instance )
|
225
|
-
end
|
226
|
-
|
227
|
-
def behaviour_name
|
228
|
-
wrappers = []
|
229
|
-
wrappers << "pres" unless self.pres.empty?
|
230
|
-
wrappers << "arounds" unless self.arounds.empty?
|
231
|
-
wrappers << "posts" unless self.posts.empty?
|
232
|
-
|
233
|
-
"behaviour_" + ( wrappers.empty? ? "without_wrappers" :
|
234
|
-
"with_" + wrappers.join( "_and_" ) )
|
235
|
-
end
|
236
|
-
|
237
|
-
def behaviour_without_wrappers( instance )
|
238
|
-
self.core.bind( instance )
|
239
|
-
end
|
240
|
-
|
241
|
-
def behaviour_with_pres( instance )
|
242
|
-
combined_pres = self.combine_pres( instance )
|
243
|
-
bound_core = self.bind_core( instance )
|
244
|
-
|
245
|
-
lambda do | *arguments |
|
246
|
-
nature = MethodNature.new( arguments, nil, false )
|
247
|
-
|
248
|
-
combined_pres.call( nature )
|
249
|
-
unless nature.break
|
250
|
-
bound_core.call( *nature.arguments )
|
251
|
-
else
|
252
|
-
nature.return_value
|
38
|
+
def context_proxy_for_module(methods_module)
|
39
|
+
proxies[methods_module] ||= begin
|
40
|
+
c = Class.new
|
41
|
+
c.class_eval(%Q{
|
42
|
+
include ObjectSpace._id2ref(#{methods_module.object_id})
|
43
|
+
}, __FILE__, __LINE__)
|
44
|
+
c.new
|
253
45
|
end
|
254
46
|
end
|
255
|
-
end
|
256
|
-
|
257
|
-
def behaviour_with_posts( instance )
|
258
|
-
bound_core = self.bind_core( instance )
|
259
|
-
combined_posts = self.combine_posts( instance )
|
260
|
-
|
261
|
-
lambda do | *arguments |
|
262
|
-
nature = MethodNature.new( arguments, nil, false )
|
263
|
-
|
264
|
-
nature.return_value = bound_core.call( *arguments )
|
265
|
-
combined_posts.call( nature )
|
266
|
-
|
267
|
-
nature.return_value
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
def behaviour_with_pres_and_posts( instance )
|
272
|
-
combined_pres = self.combine_pres( instance )
|
273
|
-
bound_core = self.bind_core( instance )
|
274
|
-
combined_posts = self.combine_posts( instance )
|
275
|
-
|
276
|
-
lambda do | *arguments |
|
277
|
-
nature = MethodNature.new( arguments, nil, false )
|
278
47
|
|
279
|
-
|
280
|
-
unless
|
281
|
-
|
282
|
-
|
48
|
+
def on_class_method_added(contextified_class, method_name, version)
|
49
|
+
unless methods_modules_containing_method(contextified_class,
|
50
|
+
method_name).empty?
|
51
|
+
replace_core_method(contextified_class, method_name, version)
|
283
52
|
end
|
284
|
-
nature.return_value
|
285
53
|
end
|
286
|
-
end
|
287
|
-
|
288
|
-
def behaviour_with_arounds( instance )
|
289
|
-
bound_core = self.bind_core( instance )
|
290
|
-
bound_arounds = self.bind_arounds( instance )
|
291
54
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
55
|
+
def on_wrapper_method_added(methods_module, method_name, version)
|
56
|
+
self.definitions.collect do | each_class, each_methods_modules |
|
57
|
+
if each_methods_modules.include?(methods_module)
|
58
|
+
each_class
|
59
|
+
end
|
60
|
+
end.compact.each do | contextified_class |
|
61
|
+
replace_core_method(contextified_class, method_name, 0)
|
299
62
|
end
|
300
|
-
nature.return_value
|
301
63
|
end
|
302
|
-
end
|
303
64
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
bound_arounds = self.bind_arounds( instance )
|
308
|
-
|
309
|
-
lambda do | *arguments |
|
310
|
-
nature = MethodNature.new( arguments, nil, false )
|
311
|
-
|
312
|
-
combined_pres.call( nature )
|
313
|
-
unless nature.break
|
314
|
-
working_arounds = bound_arounds.clone
|
315
|
-
nature.block = around_block( nature, working_arounds, bound_core )
|
316
|
-
catch( :break_in_around ) do
|
317
|
-
working_arounds.shift.call( nature )
|
318
|
-
end
|
319
|
-
end
|
320
|
-
nature.return_value
|
65
|
+
def replace_core_method(contextified_class, method_name, version)
|
66
|
+
ContextR::observe_core_method(contextified_class, method_name.to_sym,
|
67
|
+
version)
|
321
68
|
end
|
322
|
-
end
|
323
|
-
|
324
|
-
def behaviour_with_arounds_and_posts( instance )
|
325
|
-
bound_core = self.bind_core( instance )
|
326
|
-
bound_arounds = self.bind_arounds( instance )
|
327
|
-
combined_posts = self.combine_posts( instance )
|
328
|
-
|
329
|
-
lambda do | *arguments |
|
330
|
-
working_arounds = bound_arounds.clone
|
331
|
-
nature = MethodNature.new( arguments, nil, false,
|
332
|
-
around_block( nature, working_arounds, bound_core ) )
|
333
69
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
70
|
+
def register_callbacks(cclass, mmodule)
|
71
|
+
{ :on_wrapper_method_added => mmodule,
|
72
|
+
:on_class_method_added => cclass }.each do | callback, klass |
|
73
|
+
ContextR::EventMachine.register(self, callback,
|
74
|
+
:on_event => :method_added,
|
75
|
+
:in_class => klass)
|
76
|
+
end
|
77
|
+
end
|
341
78
|
end
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
combined_posts = self.combine_posts( instance )
|
348
|
-
|
349
|
-
lambda do | *arguments |
|
350
|
-
nature = MethodNature.new( arguments, nil, false )
|
351
|
-
|
352
|
-
combined_pres.call( nature )
|
353
|
-
unless nature.break
|
354
|
-
working_arounds = bound_arounds.clone
|
355
|
-
nature.block = around_block( nature, working_arounds, bound_core )
|
356
|
-
catch( :break_in_around ) do
|
357
|
-
working_arounds.shift.call( nature )
|
358
|
-
end
|
359
|
-
unless nature.break
|
360
|
-
combined_posts.call( nature )
|
361
|
-
end
|
362
|
-
end
|
363
|
-
nature.return_value
|
364
|
-
end
|
365
|
-
end
|
366
|
-
|
367
|
-
|
368
|
-
# helpers
|
369
|
-
def combine_pres( instance )
|
370
|
-
bound_pres = self.pres.collect { | p | p.bind( instance ) }
|
371
|
-
lambda do | nature |
|
372
|
-
bound_pres.each do | bound_pre |
|
373
|
-
bound_pre.call( nature )
|
374
|
-
break if nature.break
|
375
|
-
end
|
376
|
-
end
|
377
|
-
end
|
378
|
-
|
379
|
-
def bind_arounds( instance )
|
380
|
-
self.arounds.collect { | a | a.bind( instance ) }
|
381
|
-
end
|
382
|
-
|
383
|
-
def around_block( nature, bound_arounds, bound_core )
|
384
|
-
lambda do
|
385
|
-
unless bound_arounds.empty?
|
386
|
-
bound_arounds.shift.call( nature )
|
387
|
-
throw( :break_in_around ) if nature.break
|
388
|
-
else
|
389
|
-
nature.return_value = bound_core.call( *nature.arguments )
|
390
|
-
end
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
def bind_core( instance )
|
395
|
-
self.core.bind( instance )
|
396
|
-
end
|
397
|
-
|
398
|
-
def combine_posts( instance )
|
399
|
-
bound_posts = self.posts.collect { | p | p.bind( instance ) }
|
400
|
-
lambda do | nature |
|
401
|
-
bound_posts.reverse.each do | bound_post |
|
402
|
-
bound_post.call( nature )
|
403
|
-
break if nature.break
|
404
|
-
end
|
405
|
-
nature.return_value
|
406
|
-
end
|
79
|
+
|
80
|
+
self.extend(ClassMethods)
|
81
|
+
|
82
|
+
def self.inherited(klass)
|
83
|
+
klass.extend(ClassMethods)
|
407
84
|
end
|
408
85
|
end
|
409
86
|
end
|
410
|
-
|