roda-container 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/README.md +33 -1
- data/lib/roda/plugins/container.rb +35 -13
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 15d116dc716eb7e2220f95bab7a4179e53737569
|
4
|
+
data.tar.gz: 02779f0dd1d9e5c7c6ab4bec115abd2f65d1d586
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7134e5541427b5da8d8b49f217baccdc3d5063fe6a350ccbf19c09b68167821f97bdc5489d887c4ae032a0749f7c3b46b3d9bea9965dc85f62980cb7ebf6600d
|
7
|
+
data.tar.gz: fcafa937f4f20c140ea30397a28478631381aad60f9a732e49af9e0d6260cbcc26d6568b82bdc344cb0edd9395027fd247dd7a0e1e8537601b83fa7123cb00d0
|
data/README.md
CHANGED
@@ -45,11 +45,43 @@ end
|
|
45
45
|
|
46
46
|
MyApplication.route do |r|
|
47
47
|
# Roda responds to the instance method #call, with the call: false
|
48
|
-
# option, calling MyApplication.resolve(:app) will not attempt to call
|
48
|
+
# option, calling MyApplication.instance.resolve(:app) will not attempt to call
|
49
49
|
# it, without the option, the application would error
|
50
|
+
MyApplication.instance.register(:app, self, call: false)
|
51
|
+
end
|
52
|
+
```
|
53
|
+
|
54
|
+
## Thread safety
|
55
|
+
|
56
|
+
Please note the use of `MyApplication.instance.register` and `MyApplication.instance.resolve` above, without the calls to `Roda.instance` there is a high possiblilty of a thread safety issue when registering anything at runtime. For example:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
class MyApplication < Roda
|
60
|
+
plugin :container
|
61
|
+
end
|
62
|
+
|
63
|
+
MyApplication.route do |r|
|
64
|
+
# DO NOT DO THIS, SEE ABOVE ^^^
|
50
65
|
MyApplication.register(:app, self, call: false)
|
66
|
+
|
67
|
+
r.on 'users' do
|
68
|
+
# ...
|
69
|
+
r.get :id do |user_id|
|
70
|
+
MyApplication.resolve(:app)
|
71
|
+
end
|
72
|
+
|
73
|
+
r.post do
|
74
|
+
sleep(5)
|
75
|
+
MyApplication.resolve(:app)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
51
79
|
```
|
52
80
|
|
81
|
+
Immagine a user hitting `POST /users`, then another user hitting `GET /users/{id}` in quick succession; the first user registers their instance of app with the container, then hits the 5 second sleep, then the second user comes along, registers their instance of app with the container, the request executes and they go on their merry way.
|
82
|
+
|
83
|
+
A few seconds later the 5 second sleep is complete, and the first user resolves `:app` from the container, only to find the instance that was registered by the user hitting `GET /users/{id}`, they have just spent 5 minutes meticulously filling out your webform to create their user account, only for their payload to lost in a race condition, needless to say, you don't want this to happen.
|
84
|
+
|
53
85
|
## Contributing
|
54
86
|
|
55
87
|
1. Fork it ( https://github.com/AMHOL/roda-container )
|
@@ -31,6 +31,27 @@ class Roda
|
|
31
31
|
# MyApplication.register(:person_repository, -> { PersonRepository.new })
|
32
32
|
# MyApplication.resolve(:person_repository).first
|
33
33
|
module Container
|
34
|
+
class Container < RodaCache
|
35
|
+
def register(key, contents = nil, options = {}, &block)
|
36
|
+
if block_given?
|
37
|
+
item = block
|
38
|
+
options = contents if contents.is_a?(::Hash)
|
39
|
+
else
|
40
|
+
item = contents
|
41
|
+
end
|
42
|
+
|
43
|
+
self[key] = Content.new(item, options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def resolve(key)
|
47
|
+
content = fetch(key) do
|
48
|
+
fail ::Roda::ContainerError, "Nothing registered with the name #{key}"
|
49
|
+
end
|
50
|
+
|
51
|
+
content.call
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
34
55
|
class Content
|
35
56
|
attr_reader :item, :options
|
36
57
|
|
@@ -54,7 +75,7 @@ class Roda
|
|
54
75
|
private :container
|
55
76
|
|
56
77
|
def self.extended(subclass)
|
57
|
-
subclass.instance_variable_set(:@container,
|
78
|
+
subclass.instance_variable_set(:@container, Container.new)
|
58
79
|
super
|
59
80
|
end
|
60
81
|
|
@@ -63,28 +84,29 @@ class Roda
|
|
63
84
|
super
|
64
85
|
end
|
65
86
|
|
87
|
+
def instance
|
88
|
+
Thread.current[:__container__]
|
89
|
+
end
|
90
|
+
|
66
91
|
def register(key, contents = nil, options = {}, &block)
|
67
|
-
|
68
|
-
item = block
|
69
|
-
options = contents if contents.is_a?(::Hash)
|
70
|
-
else
|
71
|
-
item = contents
|
72
|
-
end
|
73
|
-
container[key] = Roda::RodaPlugins::Container::Content.new(item, options)
|
92
|
+
container.register(key, contents, options, &block)
|
74
93
|
end
|
75
94
|
|
76
95
|
def resolve(key)
|
77
|
-
|
78
|
-
fail ::Roda::ContainerError, "Nothing registered with the name #{key}"
|
79
|
-
end
|
80
|
-
|
81
|
-
content.call
|
96
|
+
container.resolve(key)
|
82
97
|
end
|
83
98
|
|
84
99
|
def detach_container
|
85
100
|
@container = container.dup
|
86
101
|
end
|
87
102
|
end
|
103
|
+
|
104
|
+
module InstanceMethods
|
105
|
+
def call(*args, &block)
|
106
|
+
Thread.current[:__container__] = self.class.send(:container).dup
|
107
|
+
super
|
108
|
+
end
|
109
|
+
end
|
88
110
|
end
|
89
111
|
|
90
112
|
register_plugin(:container, Container)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda-container
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Holland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ~>
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rack-test
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
description: A plugin for Roda which turns your application into a (IoC) container
|
70
84
|
email:
|
71
85
|
- andyholland1991@aol.com
|