contextr 0.1.1 → 0.1.9
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.tar.gz.sig +2 -2
- data/History.txt +8 -0
- data/Manifest.txt +15 -0
- data/Rakefile +2 -2
- data/lib/contextr.rb +2 -1
- data/lib/contextr/class_methods.rb +19 -15
- data/lib/contextr/core_ext/module.rb +18 -39
- data/lib/contextr/core_ext/object.rb +1 -68
- data/lib/contextr/event_machine.rb +3 -3
- data/lib/contextr/inner_class.rb +47 -0
- data/lib/contextr/layer.rb +62 -68
- data/lib/contextr/version.rb +1 -1
- data/lib/ext/dynamic.rb +2 -2
- data/spec/contextr_spec.rb +36 -30
- data/test/lib/example_test.rb +59 -0
- data/test/lib/literate_markaby_test.rb +97 -0
- data/test/lib/literate_maruku_test.rb +108 -0
- data/test/test_class_side.mkd +234 -0
- data/test/test_class_side.rb +1 -222
- data/test/test_contextr.rb +0 -12
- data/test/test_dynamic_scope.mkd +61 -0
- data/test/test_dynamic_scope.rb +4 -0
- data/test/test_dynamics.mkd +201 -0
- data/test/test_dynamics.rb +1 -204
- data/test/test_hello_world.mkd +70 -0
- data/test/test_hello_world.rb +4 -0
- data/test/test_helper.rb +4 -53
- data/test/test_introduction.mkd +325 -0
- data/test/test_introduction.rb +1 -308
- data/test/test_layer_state.mkd +170 -0
- data/test/test_layer_state.rb +1 -176
- data/test/test_meta_api.mkd +21 -0
- data/test/test_meta_api.rb +4 -0
- data/test/test_ordering.mkd +142 -0
- data/test/test_ordering.rb +1 -144
- metadata +65 -41
- metadata.gz.sig +0 -0
data.tar.gz.sig
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
&�3��Q��<��o;\ؿ}0�`Y�G��(��%���z$9P�#��xj���O�N0*�kKK@\!�P�J3�ŵQ�S�$�Ds�K�f�/@� ��o0f��Sz�)ٓ/?f#�&bD��186� o�M�GU�Ha��;��uq�{�:�f)���D�W�ŭ��"5ǹ7֦�m��X9s쬽��X�&�m�
|
2
|
+
=����ȄJN�r��'���"kU{�v�nS̹��=��s#{>��㴯/<u�h�jQBN8(G ,z8
|
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -11,6 +11,7 @@ lib/contextr/core_ext.rb
|
|
11
11
|
lib/contextr/core_ext/module.rb
|
12
12
|
lib/contextr/core_ext/object.rb
|
13
13
|
lib/contextr/event_machine.rb
|
14
|
+
lib/contextr/inner_class.rb
|
14
15
|
lib/contextr/layer.rb
|
15
16
|
lib/contextr/modules/mutex_code.rb
|
16
17
|
lib/contextr/modules/unique_id.rb
|
@@ -23,10 +24,24 @@ setup.rb
|
|
23
24
|
spec/contextr_spec.rb
|
24
25
|
spec/spec.opts
|
25
26
|
spec/spec_helper.rb
|
27
|
+
test/lib/example_test.rb
|
28
|
+
test/lib/literate_markaby_test.rb
|
29
|
+
test/lib/literate_maruku_test.rb
|
30
|
+
test/test_class_side.mkd
|
26
31
|
test/test_class_side.rb
|
27
32
|
test/test_contextr.rb
|
33
|
+
test/test_dynamic_scope.mkd
|
34
|
+
test/test_dynamic_scope.rb
|
35
|
+
test/test_dynamics.mkd
|
28
36
|
test/test_dynamics.rb
|
37
|
+
test/test_hello_world.mkd
|
38
|
+
test/test_hello_world.rb
|
29
39
|
test/test_helper.rb
|
40
|
+
test/test_introduction.mkd
|
30
41
|
test/test_introduction.rb
|
42
|
+
test/test_layer_state.mkd
|
31
43
|
test/test_layer_state.rb
|
44
|
+
test/test_meta_api.mkd
|
45
|
+
test/test_meta_api.rb
|
46
|
+
test/test_ordering.mkd
|
32
47
|
test/test_ordering.rb
|
data/Rakefile
CHANGED
@@ -107,8 +107,8 @@ task :website => [:website_generate, :website_upload, :publish_docs]
|
|
107
107
|
desc 'Release the website and new gem version'
|
108
108
|
task :deploy => [:check_version, :website, :release] do
|
109
109
|
puts "Remember to create SVN tag:"
|
110
|
-
puts "svn copy svn+ssh
|
111
|
-
"svn+ssh
|
110
|
+
puts "svn copy svn+ssh://rubyforge.org/var/svn/#{PATH}/trunk " +
|
111
|
+
"svn+ssh://rubyforge.org/var/svn/#{PATH}/tags/contextr-#{VERS} "
|
112
112
|
puts "Suggested comment:"
|
113
113
|
puts "Tagging release #{CHANGES}"
|
114
114
|
end
|
data/lib/contextr.rb
CHANGED
@@ -11,7 +11,8 @@ end
|
|
11
11
|
|
12
12
|
# the basic library code
|
13
13
|
%w{public_api class_methods layer
|
14
|
-
event_machine core_ext version
|
14
|
+
event_machine core_ext version
|
15
|
+
inner_class}.each { | file |
|
15
16
|
require File.dirname(__FILE__) + "/contextr/#{file}" }
|
16
17
|
|
17
18
|
unless Dynamic.variables.include?( :layers )
|
@@ -2,17 +2,17 @@ module ContextR # :nodoc:
|
|
2
2
|
module ClassMethods # :nodoc:
|
3
3
|
include MutexCode
|
4
4
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
else
|
9
|
-
super
|
5
|
+
def stored_core_methods
|
6
|
+
@stored_core_methods ||= Hash.new do |hash, key|
|
7
|
+
hash[key] = Hash.new
|
10
8
|
end
|
11
9
|
end
|
12
10
|
|
13
|
-
def
|
14
|
-
@
|
15
|
-
hash[key] = Hash.new
|
11
|
+
def stored_module_definitions
|
12
|
+
@stored_module_definitions ||= Hash.new do |hash, key|
|
13
|
+
hash[key] = Hash.new do |hash, key|
|
14
|
+
hash[key] = Module.new
|
15
|
+
end
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -25,24 +25,22 @@ module ContextR # :nodoc:
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def layers_as_classes
|
28
|
-
|
29
|
-
l.scan(/(.+)Layer/).first.first.underscore.to_sym
|
30
|
-
}
|
28
|
+
@layers.values
|
31
29
|
end
|
32
30
|
|
33
31
|
def symbol_by_layer(lay)
|
34
|
-
|
32
|
+
@layers.index(lay)
|
35
33
|
end
|
36
34
|
|
37
35
|
def layer_by_symbol(sym)
|
38
|
-
|
36
|
+
@layers[sym] ||= ContextR::Layer.new
|
39
37
|
end
|
40
38
|
|
41
39
|
def call_methods_stack(stack, receiver, method_name, arguments, block)
|
42
40
|
if stack.size == 1
|
43
41
|
stack.pop.call(*arguments, &block)
|
44
42
|
else
|
45
|
-
stack.pop.
|
43
|
+
stack.pop.__send__(method_name, *arguments) do | action, *rest_args |
|
46
44
|
case action
|
47
45
|
when :receiver
|
48
46
|
receiver
|
@@ -62,7 +60,9 @@ module ContextR # :nodoc:
|
|
62
60
|
method_name, arguments, block)
|
63
61
|
proxies = []
|
64
62
|
active_layers_as_classes.each do |layer|
|
65
|
-
proxies += layer.context_proxies(
|
63
|
+
proxies += layer.context_proxies(receiver,
|
64
|
+
contextified_class,
|
65
|
+
method_name)
|
66
66
|
end.compact
|
67
67
|
|
68
68
|
proxies << core_proxy(receiver, contextified_class, method_name)
|
@@ -104,6 +104,10 @@ module ContextR # :nodoc:
|
|
104
104
|
def meta_method?(method_name)
|
105
105
|
method_name.to_s =~ /method_added(_with(out)?_contextr_listener)?/
|
106
106
|
end
|
107
|
+
|
108
|
+
def self.extended(base)
|
109
|
+
base.instance_variable_set(:@layers, {})
|
110
|
+
end
|
107
111
|
end
|
108
112
|
self.extend(ClassMethods)
|
109
113
|
end
|
@@ -1,41 +1,16 @@
|
|
1
|
-
#--
|
2
|
-
# The aliasing of these methods is done in a class_eval block to avoid code
|
3
|
-
# documentation by RDoc.
|
4
|
-
#++
|
5
|
-
Module.class_eval do
|
6
|
-
alias_method :include_without_layers, :include
|
7
|
-
end
|
8
|
-
|
9
1
|
class Module
|
10
|
-
|
11
|
-
def include_with_layers(associations) # :nodoc:
|
12
|
-
associations.each do | modul, layer |
|
13
|
-
ContextR::layer_by_symbol(layer).add_method_collection(self, modul)
|
14
|
-
end
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
# call-seq:
|
19
|
-
# include(module, ...) => self
|
20
|
-
# include(module => layer_qualifier, ...) => self
|
21
|
-
#
|
22
|
-
# Invokes <code>Module.append_features</code> on each parameter in turn.
|
2
|
+
# Adds context-dependent behaviour to instances.
|
23
3
|
#
|
24
|
-
# If called with a hash, adds the module to the given layer. The behaviour
|
25
|
-
# is associated with the class side of the object.
|
26
|
-
#
|
27
|
-
# module Mod
|
28
|
-
# def name
|
29
|
-
# "Hello from #{yield(:next)}.\n"
|
30
|
-
# end
|
31
|
-
# end
|
32
|
-
#
|
33
4
|
# class Klass
|
34
5
|
# def name
|
35
6
|
# "Klass"
|
36
7
|
# end
|
37
8
|
#
|
38
|
-
#
|
9
|
+
# in_layer :hello do
|
10
|
+
# def name
|
11
|
+
# "Hello from #{super}.\n"
|
12
|
+
# end
|
13
|
+
# end
|
39
14
|
# end
|
40
15
|
#
|
41
16
|
# k = Klass.new
|
@@ -45,13 +20,17 @@ class Module
|
|
45
20
|
# end
|
46
21
|
# k.name #=> "Klass.\n"
|
47
22
|
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
23
|
+
# Note: in_layer automatically generates the inner module
|
24
|
+
# and attaches it to the given layer. It is guaranteed, that the inner module
|
25
|
+
# used for method definitons will always be the same for any layer x class
|
26
|
+
# combination.
|
27
|
+
def in_layer(layer_symbol, &block)
|
28
|
+
extension = ContextR::stored_module_definitions[layer_symbol][self]
|
29
|
+
|
30
|
+
extension.module_eval(&block) if block_given?
|
53
31
|
|
54
|
-
|
55
|
-
|
56
|
-
|
32
|
+
ContextR::layer_by_symbol(layer_symbol).add_method_collection(self,
|
33
|
+
extension)
|
34
|
+
extension
|
35
|
+
end
|
57
36
|
end
|
@@ -1,71 +1,4 @@
|
|
1
|
-
|
2
|
-
# The aliasing of these methods is done in a class_eval block to avoid code
|
3
|
-
# documentation by RDoc.
|
4
|
-
#++
|
5
|
-
Object.class_eval do
|
6
|
-
alias_method :extend_without_layers, :extend
|
7
|
-
end
|
8
|
-
|
9
|
-
class Object
|
10
|
-
def extend_with_layers(associations) # :nodoc:
|
11
|
-
klass = class << self; self; end
|
12
|
-
associations.each do | modul, layer |
|
13
|
-
ContextR::layer_by_symbol(layer).add_method_collection(klass, modul)
|
14
|
-
end
|
15
|
-
self
|
16
|
-
end
|
17
|
-
|
18
|
-
# call-seq:
|
19
|
-
# obj.extend(module, ...) => obj
|
20
|
-
# obj.extend(module => layer_qualifier, ...) => obj
|
21
|
-
#
|
22
|
-
# Adds to _obj_ the instance methods from each module given as a
|
23
|
-
# parameter.
|
24
|
-
#
|
25
|
-
# module Mod
|
26
|
-
# def hello
|
27
|
-
# "Hello from Mod.\n"
|
28
|
-
# end
|
29
|
-
# end
|
30
|
-
#
|
31
|
-
# class Klass
|
32
|
-
# def hello
|
33
|
-
# "Hello from Klass.\n"
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
#
|
37
|
-
# k = Klass.new
|
38
|
-
# k.hello #=> "Hello from Klass.\n"
|
39
|
-
# k.extend(Mod) #=> #<Klass:0x401b3bc8>
|
40
|
-
# k.hello #=> "Hello from Mod.\n"
|
41
|
-
#
|
42
|
-
# If called with a hash, adds the module to the given layer. The behaviour
|
43
|
-
# is associated with the class side of the object.
|
44
|
-
#
|
45
|
-
# module Mod
|
46
|
-
# def name
|
47
|
-
# "Hello from #{yield(:next)}.\n"
|
48
|
-
# end
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# class Klass
|
52
|
-
# def name
|
53
|
-
# "Klass"
|
54
|
-
# end
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# k = Klass.new
|
58
|
-
# k.extend(Mod => :hello) #=> #<Klass:0x401b3bc8>
|
59
|
-
# k.name #=> "Klass.\n"
|
60
|
-
# ContextR::with_layer :hello do
|
61
|
-
# k.name #=> "Hello from Klass.\n"
|
62
|
-
# end
|
63
|
-
# k.name #=> "Klass.\n"
|
64
|
-
def extend(*args)
|
65
|
-
args.first.is_a?(Module) ? extend_without_layers(*args) :
|
66
|
-
extend_with_layers(*args)
|
67
|
-
end
|
68
|
-
|
1
|
+
class Object #:nodoc:
|
69
2
|
def behavioural_class #:nodoc:
|
70
3
|
if self.kind_of?(Module)
|
71
4
|
class << self; self; end
|
@@ -4,7 +4,7 @@ module ContextR
|
|
4
4
|
include UniqueId
|
5
5
|
|
6
6
|
def listeners
|
7
|
-
@listeners ||= {
|
7
|
+
@listeners ||= {:method_added => {}}
|
8
8
|
end
|
9
9
|
|
10
10
|
def register(listener, callback, options)
|
@@ -20,8 +20,8 @@ module ContextR
|
|
20
20
|
|
21
21
|
def on_method_added(modul, name)
|
22
22
|
version = self.new_unique_id
|
23
|
-
self.listeners[:method_added][modul].each do |
|
24
|
-
listener.send(
|
23
|
+
self.listeners[:method_added][modul].to_a.each do |listener, method|
|
24
|
+
listener.send(method, modul, name, version)
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ContextR
|
2
|
+
class InnerClass # :nodoc:
|
3
|
+
#--
|
4
|
+
# Copyright 2004, 2006 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#++
|
11
|
+
class << self
|
12
|
+
# Hide the method named +name+ in the BlankSlate class. Don't
|
13
|
+
# hide +instance_eval+ or any method beginning with "__".
|
14
|
+
def hide(name)
|
15
|
+
if instance_methods.include?(name.to_s) and
|
16
|
+
name !~ /^(__|instance_eval)/
|
17
|
+
@hidden_methods ||= {}
|
18
|
+
@hidden_methods[name.to_sym] = instance_method(name)
|
19
|
+
undef_method name
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_hidden_method(name)
|
24
|
+
@hidden_methods ||= {}
|
25
|
+
@hidden_methods[name] || superclass.find_hidden_method(name)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Redefine a previously hidden method so that it may be called on a blank
|
29
|
+
# slate object.
|
30
|
+
def reveal(name)
|
31
|
+
bound_method = nil
|
32
|
+
unbound_method = find_hidden_method(name)
|
33
|
+
fail "Don't know how to reveal method '#{name}'" unless unbound_method
|
34
|
+
define_method(name) do |*args|
|
35
|
+
bound_method ||= unbound_method.bind(self)
|
36
|
+
bound_method.call(*args)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
instance_methods.each { |m| hide(m) }
|
42
|
+
|
43
|
+
def method_missing(method_name, *rest_args)
|
44
|
+
yield(:next, *rest_args)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/contextr/layer.rb
CHANGED
@@ -1,88 +1,82 @@
|
|
1
1
|
module ContextR # :nodoc:
|
2
2
|
class Layer # :nodoc: all
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
3
|
+
def definitions
|
4
|
+
@definitions ||= {}
|
5
|
+
end
|
6
|
+
def proxies
|
7
|
+
@proxies ||= {}
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
def add_method_collection(contextified_class, methods_module)
|
11
|
+
definitions[contextified_class] ||= []
|
12
|
+
definitions[contextified_class].delete(methods_module)
|
13
|
+
definitions[contextified_class].push(methods_module)
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
20
|
-
register_callbacks(contextified_class, methods_module)
|
15
|
+
(methods_module.instance_methods &
|
16
|
+
contextified_class.instance_methods).each do | method_name |
|
17
|
+
replace_core_method(contextified_class, method_name, 0)
|
21
18
|
end
|
19
|
+
register_callbacks(contextified_class, methods_module)
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
else
|
29
|
-
[]
|
22
|
+
def methods_modules_containing_method(contextified_class, method_name)
|
23
|
+
if definitions.include?(contextified_class)
|
24
|
+
definitions[contextified_class].select do | methods_module |
|
25
|
+
methods_module.instance_methods.include?(method_name.to_s)
|
30
26
|
end
|
27
|
+
else
|
28
|
+
[]
|
31
29
|
end
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
def context_proxy_for_module(methods_module)
|
41
|
-
proxies[methods_module] ||= begin
|
42
|
-
c = Class.new
|
43
|
-
c.class_eval(%Q{
|
44
|
-
include ObjectSpace._id2ref(#{methods_module.object_id})
|
45
|
-
}, __FILE__, __LINE__)
|
46
|
-
c.new
|
47
|
-
end
|
48
|
-
end
|
32
|
+
def context_proxies(receiver, contextified_class, method_name)
|
33
|
+
methods_modules_containing_method(contextified_class, method_name).
|
34
|
+
collect do | methods_module |
|
35
|
+
context_proxy_for_module(receiver, methods_module)
|
36
|
+
end.reverse
|
37
|
+
end
|
49
38
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
39
|
+
def context_proxy_for_module(receiver, methods_module)
|
40
|
+
proxies[methods_module] ||= begin
|
41
|
+
c = Class.new(ContextR::InnerClass)
|
42
|
+
c.class_eval(%Q{
|
43
|
+
include ObjectSpace._id2ref(#{methods_module.object_id})
|
44
|
+
}, __FILE__, __LINE__)
|
45
|
+
c.new
|
55
46
|
end
|
47
|
+
end
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
end.compact.each do | contextified_class |
|
63
|
-
replace_core_method(contextified_class, method_name, 0)
|
64
|
-
end
|
49
|
+
def on_class_method_added(contextified_class, method_name, version)
|
50
|
+
unless methods_modules_containing_method(contextified_class,
|
51
|
+
method_name).empty?
|
52
|
+
replace_core_method(contextified_class, method_name, version)
|
65
53
|
end
|
54
|
+
end
|
66
55
|
|
67
|
-
|
68
|
-
|
69
|
-
|
56
|
+
def on_wrapper_method_added(methods_module, method_name, version)
|
57
|
+
self.definitions.collect do | each_class, each_methods_modules |
|
58
|
+
if each_methods_modules.include?(methods_module)
|
59
|
+
each_class
|
60
|
+
end
|
61
|
+
end.compact.select do |contextified_class|
|
62
|
+
contextified_class.instance_methods.include?(method_name.to_s)
|
63
|
+
end.each do | contextified_class |
|
64
|
+
replace_core_method(contextified_class, method_name, 0)
|
70
65
|
end
|
66
|
+
end
|
71
67
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
ContextR::EventMachine.register(self, callback,
|
76
|
-
:on_event => :method_added,
|
77
|
-
:in_class => klass)
|
78
|
-
end
|
79
|
-
end
|
68
|
+
def replace_core_method(contextified_class, method_name, version)
|
69
|
+
ContextR::observe_core_method(contextified_class, method_name.to_sym,
|
70
|
+
version)
|
80
71
|
end
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
72
|
+
|
73
|
+
def register_callbacks(cclass, mmodule)
|
74
|
+
{:on_wrapper_method_added => mmodule,
|
75
|
+
:on_class_method_added => cclass }.each do | callback, klass |
|
76
|
+
ContextR::EventMachine.register(self, callback,
|
77
|
+
:on_event => :method_added,
|
78
|
+
:in_class => klass)
|
79
|
+
end
|
86
80
|
end
|
87
81
|
end
|
88
82
|
end
|