roda-container 0.1.0 → 0.1.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.
- checksums.yaml +4 -4
- data/README.md +3 -57
- data/lib/roda/plugins/container.rb +5 -80
- metadata +29 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7603e25379a7502e5fd5a3fe2a78c33a4f72f487
|
4
|
+
data.tar.gz: 423b5dbee4587c87bb8eef289f489a448ee1a265
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4146cf61ef4a13aa6b64ab4efe5506732729751b5efe7cbd3929dcc0325dcf6bcba83d6ec965d73002efd626ac024ac7f0c65fd755c4ead8ab39ef263fe9c52e
|
7
|
+
data.tar.gz: 6445f2c0494b1d1570be7e9c1120906e1f508dbb4290fd76462a272c7434351aeba561544ffb14a5cd31158a70398663a68a51f497db8e861e962affe572f699
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ A plugin for Roda which turns your application into a (IoC) container
|
|
5
5
|
## Installation
|
6
6
|
|
7
7
|
```ruby
|
8
|
-
gem 'roda-container'
|
8
|
+
gem 'roda-container'
|
9
9
|
```
|
10
10
|
|
11
11
|
## Usage
|
@@ -27,69 +27,15 @@ MyApplication.resolve(:user_repository).first
|
|
27
27
|
|
28
28
|
class PersonRepository
|
29
29
|
def first
|
30
|
-
{ name: '
|
30
|
+
{ name: 'Jill' }
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
34
|
MyApplication.register(:person_repository, -> { PersonRepository.new })
|
35
35
|
MyApplication.resolve(:person_repository).first
|
36
|
-
# => {:name=>"
|
36
|
+
# => {:name=>"Jill"}
|
37
37
|
```
|
38
38
|
|
39
|
-
If you want to register a proc, or anything that responds to call, without calling when resolving it, you can pass the `call: false` option:
|
40
|
-
|
41
|
-
```ruby
|
42
|
-
class MyApplication < Roda
|
43
|
-
plugin :container
|
44
|
-
end
|
45
|
-
|
46
|
-
MyApplication.route do |r|
|
47
|
-
# Roda responds to the instance method #call, with the call: false
|
48
|
-
# option, calling MyApplication.instance.resolve(:app) will not attempt to call
|
49
|
-
# it, without the option, the application would error
|
50
|
-
register(:app, self, call: false) # Roda#register, regiser with the request container
|
51
|
-
end
|
52
|
-
```
|
53
|
-
|
54
|
-
## Thread safety
|
55
|
-
|
56
|
-
Please note the use of and `MyApplication.instance.resolve` above, without the call to `Roda.instance` the item will not be present in the container, as it was registered with the request container (using Roda#register), without this, there is 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 ^^^
|
65
|
-
MyApplication.register(:app, self, call: false) # Roda.register, register with the global container
|
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
|
79
|
-
```
|
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 global container, then hits the 5 second sleep, then the second user comes along, registers their instance of app with the global 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 global container, only to find the application 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 be lost in a race condition, needless to say - you don't want this to happen.
|
84
|
-
|
85
|
-
This is preventable by registering anything specific to a request with the request container, this is done using the `Roda#register` method, i.e.
|
86
|
-
|
87
|
-
```ruby
|
88
|
-
MyApplication.route do |r|
|
89
|
-
register(:app, self, call: false) # Roda#register, regiser with the request container
|
90
|
-
end
|
91
|
-
``
|
92
|
-
|
93
39
|
## Contributing
|
94
40
|
|
95
41
|
1. Fork it ( https://github.com/AMHOL/roda-container )
|
@@ -1,6 +1,6 @@
|
|
1
|
-
|
2
|
-
ContainerError = Class.new(::Exception)
|
1
|
+
require 'dry-container'
|
3
2
|
|
3
|
+
class Roda
|
4
4
|
module RodaPlugins
|
5
5
|
# The container plugin allows your application to
|
6
6
|
# act as a container, you can register values
|
@@ -31,85 +31,10 @@ class Roda
|
|
31
31
|
# MyApplication.register(:person_repository, -> { PersonRepository.new })
|
32
32
|
# MyApplication.resolve(:person_repository).first
|
33
33
|
module Container
|
34
|
-
|
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
|
-
|
55
|
-
class Content
|
56
|
-
attr_reader :item, :options
|
57
|
-
|
58
|
-
def initialize(item, options = {})
|
59
|
-
@item, @options = item, {
|
60
|
-
call: item.is_a?(::Proc)
|
61
|
-
}.merge(options)
|
62
|
-
end
|
63
|
-
|
64
|
-
def call
|
65
|
-
if options[:call] == true
|
66
|
-
item.call
|
67
|
-
else
|
68
|
-
item
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
module ClassMethods
|
74
|
-
attr_reader :container
|
75
|
-
private :container
|
76
|
-
|
77
|
-
def self.extended(subclass)
|
78
|
-
subclass.instance_variable_set(:@container, Container.new)
|
79
|
-
super
|
80
|
-
end
|
81
|
-
|
82
|
-
def inherited(subclass)
|
83
|
-
subclass.instance_variable_set(:@container, container)
|
84
|
-
super
|
85
|
-
end
|
86
|
-
|
87
|
-
def instance
|
88
|
-
Thread.current[:__container__]
|
89
|
-
end
|
90
|
-
|
91
|
-
def register(key, contents = nil, options = {}, &block)
|
92
|
-
container.register(key, contents, options, &block)
|
93
|
-
end
|
94
|
-
|
95
|
-
def resolve(key)
|
96
|
-
container.resolve(key)
|
97
|
-
end
|
98
|
-
|
99
|
-
def detach_container
|
100
|
-
@container = container.dup
|
101
|
-
end
|
102
|
-
end
|
34
|
+
module_function
|
103
35
|
|
104
|
-
|
105
|
-
|
106
|
-
Thread.current[:__container__] = self.class.send(:container).dup
|
107
|
-
super
|
108
|
-
end
|
109
|
-
|
110
|
-
def register(*args, &block)
|
111
|
-
self.class.instance.register(*args, &block)
|
112
|
-
end
|
36
|
+
def configure(app)
|
37
|
+
app.send(:extend, Dry::Container::Mixin)
|
113
38
|
end
|
114
39
|
end
|
115
40
|
|
metadata
CHANGED
@@ -1,83 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roda-container
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
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-
|
11
|
+
date: 2015-09-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: dry-container
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
16
30
|
requirements:
|
17
|
-
- -
|
31
|
+
- - ">="
|
18
32
|
- !ruby/object:Gem::Version
|
19
33
|
version: '0'
|
20
34
|
type: :development
|
21
35
|
prerelease: false
|
22
36
|
version_requirements: !ruby/object:Gem::Requirement
|
23
37
|
requirements:
|
24
|
-
- -
|
38
|
+
- - ">="
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '0'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: roda
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- -
|
45
|
+
- - ">="
|
32
46
|
- !ruby/object:Gem::Version
|
33
47
|
version: '0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- -
|
52
|
+
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
54
|
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
|
-
- - ~>
|
59
|
+
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
61
|
version: '10.3'
|
48
62
|
type: :development
|
49
63
|
prerelease: false
|
50
64
|
version_requirements: !ruby/object:Gem::Requirement
|
51
65
|
requirements:
|
52
|
-
- - ~>
|
66
|
+
- - "~>"
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '10.3'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rspec
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
58
72
|
requirements:
|
59
|
-
- - ~>
|
73
|
+
- - "~>"
|
60
74
|
- !ruby/object:Gem::Version
|
61
75
|
version: '3.2'
|
62
76
|
type: :development
|
63
77
|
prerelease: false
|
64
78
|
version_requirements: !ruby/object:Gem::Requirement
|
65
79
|
requirements:
|
66
|
-
- - ~>
|
80
|
+
- - "~>"
|
67
81
|
- !ruby/object:Gem::Version
|
68
82
|
version: '3.2'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rack-test
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
72
86
|
requirements:
|
73
|
-
- -
|
87
|
+
- - ">="
|
74
88
|
- !ruby/object:Gem::Version
|
75
89
|
version: '0'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
|
-
- -
|
94
|
+
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
83
97
|
description: A plugin for Roda which turns your application into a (IoC) container
|
@@ -100,17 +114,17 @@ require_paths:
|
|
100
114
|
- lib
|
101
115
|
required_ruby_version: !ruby/object:Gem::Requirement
|
102
116
|
requirements:
|
103
|
-
- -
|
117
|
+
- - ">="
|
104
118
|
- !ruby/object:Gem::Version
|
105
119
|
version: '0'
|
106
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- -
|
122
|
+
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
111
125
|
requirements: []
|
112
126
|
rubyforge_project:
|
113
|
-
rubygems_version: 2.4.
|
127
|
+
rubygems_version: 2.4.5.1
|
114
128
|
signing_key:
|
115
129
|
specification_version: 4
|
116
130
|
summary: A plugin for Roda which turns your application into a (IoC) container
|