activecontext 0.1
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/lib/activecontext.rb +26 -0
- data/lib/activecontext/container.rb +62 -0
- data/lib/activecontext/rack.rb +26 -0
- data/spec/activecontext_spec.rb +178 -0
- data/spec/container_spec.rb +136 -0
- metadata +61 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require "activecontext/container"
|
2
|
+
|
3
|
+
module ActiveContext
|
4
|
+
def biject(*args)
|
5
|
+
inject(*args)
|
6
|
+
outject(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def inject(*names)
|
10
|
+
names.each do |name|
|
11
|
+
raise "invalid inject name #{name}" if methods.include?(name)
|
12
|
+
define_method name do
|
13
|
+
(value = Container.current[name]) && value.is_a?(Proc) ? value.call : value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def outject(*names)
|
19
|
+
names.each do |name|
|
20
|
+
raise "invalid outject name #{name}" if methods.include?(:"#{name}=")
|
21
|
+
define_method "#{name}=" do |*args|
|
22
|
+
Container.current[name] = args.first
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module ActiveContext
|
2
|
+
class Container
|
3
|
+
def initialize
|
4
|
+
@names = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
def register(name, ctx={}, &block)
|
8
|
+
raise "invalid context name" if methods.include?(name)
|
9
|
+
instance_variable_set("@#{name}", ctx)
|
10
|
+
|
11
|
+
eigen = class << self; self; end
|
12
|
+
eigen.send(:define_method, name) do |*args, &block2|
|
13
|
+
raise "#{name} #{args.first} already exist" if @names.key?(args.first)
|
14
|
+
@names[args.first] = name
|
15
|
+
|
16
|
+
if args.length > 1
|
17
|
+
raise "pass either a block or value. not both." if block2
|
18
|
+
self[args.first] = args[1]
|
19
|
+
end
|
20
|
+
|
21
|
+
self[args.first] = block2 if block2
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def []=(key, value)
|
26
|
+
if @names.key?(key)
|
27
|
+
self.context(@names[key])[key] = value
|
28
|
+
else
|
29
|
+
raise "unknown name #{key}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def [](key)
|
34
|
+
if @names.key?(key)
|
35
|
+
self.context(@names[key])[key]
|
36
|
+
else
|
37
|
+
raise "unknown name #{key}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def run(&block)
|
42
|
+
c = Thread.current[:contextualize]
|
43
|
+
raise "found existing container" if c && c != self
|
44
|
+
|
45
|
+
begin
|
46
|
+
Thread.current[:contextualize] = self
|
47
|
+
block.call
|
48
|
+
ensure
|
49
|
+
Thread.current[:contextualize] = nil
|
50
|
+
end unless c
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.current
|
54
|
+
Thread.current[:contextualize]
|
55
|
+
end
|
56
|
+
|
57
|
+
def context(name)
|
58
|
+
instance_variable_get("@#{name}")
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "activecontext/container"
|
2
|
+
require "rack/request"
|
3
|
+
|
4
|
+
module ActiveContext
|
5
|
+
class Rack
|
6
|
+
def initialize(app, &block)
|
7
|
+
@app = app
|
8
|
+
@block = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
req = ::Rack::Request.new(env)
|
13
|
+
|
14
|
+
container = Container.new
|
15
|
+
|
16
|
+
container.register :request, {}
|
17
|
+
container.register :session, req.session
|
18
|
+
|
19
|
+
container.instance_exec(req, &@block) if @block
|
20
|
+
|
21
|
+
container.run do
|
22
|
+
@app.call(env)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require "rspec"
|
2
|
+
require "activecontext"
|
3
|
+
|
4
|
+
describe ActiveContext do
|
5
|
+
|
6
|
+
class TestObject
|
7
|
+
end
|
8
|
+
|
9
|
+
def new_test_object
|
10
|
+
t = TestObject.new
|
11
|
+
|
12
|
+
def t.eigenclass
|
13
|
+
class << self; self; end
|
14
|
+
end
|
15
|
+
|
16
|
+
t
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "inject" do
|
20
|
+
it "should create a method for the injected name" do
|
21
|
+
o = new_test_object
|
22
|
+
o.eigenclass.instance_eval do
|
23
|
+
extend ActiveContext
|
24
|
+
inject :somename
|
25
|
+
end
|
26
|
+
o.should respond_to(:somename)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should create multiple methods when passing multiple injected names" do
|
30
|
+
o = new_test_object
|
31
|
+
o.eigenclass.instance_eval do
|
32
|
+
extend ActiveContext
|
33
|
+
inject :somename, :othername
|
34
|
+
end
|
35
|
+
o.should respond_to(:somename)
|
36
|
+
o.should respond_to(:othername)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should fail if a method with the same name as injected already exist" do
|
40
|
+
o = new_test_object
|
41
|
+
lambda do
|
42
|
+
o.eigenclass.instance_eval do
|
43
|
+
extend ActiveContext
|
44
|
+
inject :to_s
|
45
|
+
end
|
46
|
+
end.should raise_error("invalid inject name to_s")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should return the value of the injected name" do
|
50
|
+
c = ActiveContext::Container.new
|
51
|
+
c.register :request, {}
|
52
|
+
c.request :somename, :joe
|
53
|
+
|
54
|
+
c.run do
|
55
|
+
o = new_test_object
|
56
|
+
o.eigenclass.instance_eval do
|
57
|
+
extend ActiveContext
|
58
|
+
inject :somename
|
59
|
+
end
|
60
|
+
|
61
|
+
o.somename.should be(:joe)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should return the value of the injected name" do
|
66
|
+
c = ActiveContext::Container.new
|
67
|
+
c.register :request, {}
|
68
|
+
c.request :somename do
|
69
|
+
:joe
|
70
|
+
end
|
71
|
+
|
72
|
+
c.run do
|
73
|
+
o = new_test_object
|
74
|
+
o.eigenclass.instance_eval do
|
75
|
+
extend ActiveContext
|
76
|
+
inject :somename
|
77
|
+
end
|
78
|
+
|
79
|
+
o.somename.should be(:joe)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should return nil if no value exist" do
|
84
|
+
c = ActiveContext::Container.new
|
85
|
+
c.register :request, {}
|
86
|
+
c.request :somename
|
87
|
+
|
88
|
+
c.run do
|
89
|
+
o = new_test_object
|
90
|
+
o.eigenclass.instance_eval do
|
91
|
+
extend ActiveContext
|
92
|
+
inject :somename
|
93
|
+
end
|
94
|
+
|
95
|
+
o.somename.should be_nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "outject" do
|
102
|
+
it "should create a method for the injected name" do
|
103
|
+
o = new_test_object
|
104
|
+
o.eigenclass.instance_eval do
|
105
|
+
extend ActiveContext
|
106
|
+
outject :somename
|
107
|
+
end
|
108
|
+
o.should respond_to(:"somename=")
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should create multiple methods when passing multiple outjected names" do
|
112
|
+
o = new_test_object
|
113
|
+
o.eigenclass.instance_eval do
|
114
|
+
extend ActiveContext
|
115
|
+
outject :somename, :othername
|
116
|
+
end
|
117
|
+
o.should respond_to(:"somename=")
|
118
|
+
o.should respond_to(:"othername=")
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should fail if a method with the same name as outjected already exist" do
|
122
|
+
o = new_test_object
|
123
|
+
lambda do
|
124
|
+
o.eigenclass.instance_eval do
|
125
|
+
extend ActiveContext
|
126
|
+
def dummy=(key, value)
|
127
|
+
end
|
128
|
+
outject :dummy
|
129
|
+
end
|
130
|
+
end.should raise_error("invalid outject name dummy")
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should set the outjected value and read it back" do
|
134
|
+
c = ActiveContext::Container.new
|
135
|
+
ctx = {}
|
136
|
+
c.register :request, ctx
|
137
|
+
c.request :somename, :joe
|
138
|
+
|
139
|
+
c.run do
|
140
|
+
o = new_test_object
|
141
|
+
o.eigenclass.instance_eval do
|
142
|
+
extend ActiveContext
|
143
|
+
inject :somename
|
144
|
+
outject :somename
|
145
|
+
end
|
146
|
+
|
147
|
+
o.somename = :bob
|
148
|
+
o.somename.should be(:bob)
|
149
|
+
end
|
150
|
+
|
151
|
+
ctx.should eql({:somename => :bob})
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "biject" do
|
156
|
+
it "should create a method pair for injected and outjected of the passed name" do
|
157
|
+
o = new_test_object
|
158
|
+
o.eigenclass.instance_eval do
|
159
|
+
extend ActiveContext
|
160
|
+
biject :somename
|
161
|
+
end
|
162
|
+
o.should respond_to(:somename)
|
163
|
+
o.should respond_to(:"somename=")
|
164
|
+
end
|
165
|
+
|
166
|
+
it "should create multiple method pairs for injected an outjected of the passed names" do
|
167
|
+
o = new_test_object
|
168
|
+
o.eigenclass.instance_eval do
|
169
|
+
extend ActiveContext
|
170
|
+
biject :somename, :othername
|
171
|
+
end
|
172
|
+
o.should respond_to(:somename)
|
173
|
+
o.should respond_to(:"somename=")
|
174
|
+
o.should respond_to(:othername)
|
175
|
+
o.should respond_to(:"othername=")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require "rspec"
|
2
|
+
require "activecontext/container"
|
3
|
+
|
4
|
+
describe ActiveContext::Container do
|
5
|
+
|
6
|
+
it "should not contain any known names" do
|
7
|
+
ActiveContext::Container.new.instance_variable_get("@names").should be_empty
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should fail if an unknown name is accessed" do
|
11
|
+
c = ActiveContext::Container.new
|
12
|
+
lambda do
|
13
|
+
c[:key]
|
14
|
+
end.should raise_error("unknown name key")
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should fail when setting an unknown name" do
|
18
|
+
c = ActiveContext::Container.new
|
19
|
+
lambda do
|
20
|
+
c[:key] = 1
|
21
|
+
end.should raise_error("unknown name key")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set current container, run block and clean up container" do
|
25
|
+
c = ActiveContext::Container.new
|
26
|
+
c.run do
|
27
|
+
ActiveContext::Container.current.should be(c)
|
28
|
+
end
|
29
|
+
ActiveContext::Container.current.should be_nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should support nesting of the same container" do
|
33
|
+
c = ActiveContext::Container.new
|
34
|
+
c.run do
|
35
|
+
c.run do
|
36
|
+
ActiveContext::Container.current.should be(c)
|
37
|
+
end
|
38
|
+
ActiveContext::Container.current.should be(c)
|
39
|
+
end
|
40
|
+
ActiveContext::Container.current.should be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should fail when different container exist" do
|
44
|
+
c = ActiveContext::Container.new
|
45
|
+
c.run do
|
46
|
+
c2 = ActiveContext::Container.new
|
47
|
+
lambda do
|
48
|
+
c2.run
|
49
|
+
end.should raise_error("found existing container")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "registering a context" do
|
54
|
+
it "should create an instance variable with same name as context" do
|
55
|
+
c = ActiveContext::Container.new
|
56
|
+
ctx = {}
|
57
|
+
c.register :request, ctx
|
58
|
+
c.context("request").should eq(ctx)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should create a method with same name as context to declare names in this context" do
|
62
|
+
c = ActiveContext::Container.new
|
63
|
+
c.register :request, {}
|
64
|
+
c.methods(:request).should_not be_nil
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should fail when a method with same name already exist" do
|
68
|
+
c = ActiveContext::Container.new
|
69
|
+
lambda do
|
70
|
+
c.register :register, {}
|
71
|
+
end.should raise_error("invalid context name")
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "registering a name" do
|
75
|
+
it "should map the name to a context" do
|
76
|
+
c = ActiveContext::Container.new
|
77
|
+
c.register :request, {}
|
78
|
+
c.request :somename
|
79
|
+
c.instance_variable_get("@names").should eq({:somename => :request})
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should fail if name already exist" do
|
83
|
+
c = ActiveContext::Container.new
|
84
|
+
c.register :request, {}
|
85
|
+
c.request :somename
|
86
|
+
lambda do
|
87
|
+
c.request :somename
|
88
|
+
end.should raise_error("request somename already exist")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should take a initial value as second argument" do
|
92
|
+
c = ActiveContext::Container.new
|
93
|
+
c.register :request, {}
|
94
|
+
c.request :somename, :joe
|
95
|
+
c.context("request")[:somename].should be(:joe)
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should take a initial value factory as block" do
|
99
|
+
c = ActiveContext::Container.new
|
100
|
+
c.register :request, {}
|
101
|
+
factory = -> { :joe }
|
102
|
+
c.request :somename, &factory
|
103
|
+
c.context("request")[:somename].should be(factory)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should fail when passing a initial value argument and a block at the same time" do
|
107
|
+
c = ActiveContext::Container.new
|
108
|
+
c.register :request, {}
|
109
|
+
factory = -> { :joe }
|
110
|
+
lambda do
|
111
|
+
c.request :somename, :bob, &factory
|
112
|
+
end.should raise_error("pass either a block or value. not both.")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should set a value" do
|
117
|
+
c = ActiveContext::Container.new
|
118
|
+
c.register :request, {}
|
119
|
+
c.request :somename
|
120
|
+
c[:somename] = :joe
|
121
|
+
c[:somename].should be(:joe)
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should get the initial value" do
|
125
|
+
c = ActiveContext::Container.new
|
126
|
+
c.register :request, {}
|
127
|
+
c.request :somename, :joe
|
128
|
+
c.request :othername do
|
129
|
+
:bob
|
130
|
+
end
|
131
|
+
c[:somename].should be(:joe)
|
132
|
+
c[:othername].call.should be(:bob)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
metadata
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: activecontext
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- jan zimmek
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-06-04 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70264750979080 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70264750979080
|
25
|
+
description: ''
|
26
|
+
email:
|
27
|
+
- jan.zimmek@web.de
|
28
|
+
executables: []
|
29
|
+
extensions: []
|
30
|
+
extra_rdoc_files: []
|
31
|
+
files:
|
32
|
+
- lib/activecontext/container.rb
|
33
|
+
- lib/activecontext/rack.rb
|
34
|
+
- lib/activecontext.rb
|
35
|
+
- spec/activecontext_spec.rb
|
36
|
+
- spec/container_spec.rb
|
37
|
+
homepage: http://www.github.com/jzimmek/activecontext
|
38
|
+
licenses: []
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 1.9.2
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubyforge_project:
|
57
|
+
rubygems_version: 1.8.10
|
58
|
+
signing_key:
|
59
|
+
specification_version: 3
|
60
|
+
summary: ''
|
61
|
+
test_files: []
|