rohbau 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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +27 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +189 -0
- data/README.md.template +119 -0
- data/Rakefile +10 -0
- data/bin/build_readme +1 -0
- data/etc/build_readme.rb +14 -0
- data/examples/runtime.rb +49 -0
- data/examples/service_factory.rb +21 -0
- data/examples/service_factory_validation.rb +11 -0
- data/lib/rohbau/application.rb +70 -0
- data/lib/rohbau/default_memory_gateway.rb +78 -0
- data/lib/rohbau/entity.rb +41 -0
- data/lib/rohbau/event_tube.rb +42 -0
- data/lib/rohbau/index.rb +214 -0
- data/lib/rohbau/it_behaves_like.rb +26 -0
- data/lib/rohbau/minitest/exclude.rb +58 -0
- data/lib/rohbau/registry.rb +45 -0
- data/lib/rohbau/request.rb +24 -0
- data/lib/rohbau/require.rb +20 -0
- data/lib/rohbau/runtime.rb +94 -0
- data/lib/rohbau/runtime_loader.rb +67 -0
- data/lib/rohbau/service_factory.rb +37 -0
- data/lib/rohbau/shared_spec.rb +47 -0
- data/lib/rohbau/shared_specs/default_gateway.rb +305 -0
- data/lib/rohbau/use_case.rb +25 -0
- data/lib/rohbau/version.rb +3 -0
- data/lib/rohbau.rb +5 -0
- data/rohbau.gemspec +39 -0
- data/spec/event_tube_spec.rb +63 -0
- data/spec/runtime_loader_spec.rb +72 -0
- data/spec/service_factory_spec.rb +109 -0
- data/spec/shared_spec_spec.rb +44 -0
- data/spec/spec_helper.rb +12 -0
- metadata +178 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8d05d28272851e7d359b3640cdb9e4a21250f704
|
4
|
+
data.tar.gz: 183ca9c967b841d7dc8e4bc6dbdd57e222eab5fc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9b144522c39a33baa618b912f17e3f9a2a6f743a910194cc052409cd890992a0994eb629da418eb5b5d8cb1816f64159f944c9daada4b55546b1b58f71a86529
|
7
|
+
data.tar.gz: 9e6e8cd4e34c668c81172180d3ca99b64af7d5b32e9b1d19a35a72c420e2ad15eda820b0c122f6529bb2a946fe56c0a1d7dbc854bb5b4e458791edfd661e96f7
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
cache: bundler
|
4
|
+
rvm:
|
5
|
+
- ruby-head
|
6
|
+
- 2.2
|
7
|
+
- 2.1
|
8
|
+
- 2.0
|
9
|
+
- 1.9.3
|
10
|
+
- jruby
|
11
|
+
- jruby-head
|
12
|
+
- jruby-19mode # JRuby in 1.9 mode
|
13
|
+
env:
|
14
|
+
global:
|
15
|
+
- JRUBY_OPTS='--dev -J-Xmx1024M'
|
16
|
+
matrix:
|
17
|
+
fast_finish: true
|
18
|
+
allow_failures:
|
19
|
+
- rvm: ruby-head
|
20
|
+
- rvm: jruby-head
|
21
|
+
notifications:
|
22
|
+
webhooks:
|
23
|
+
urls:
|
24
|
+
- https://webhooks.gitter.im/e/c6efc69df9417bda7808
|
25
|
+
on_success: change # options: [always|never|change] default: always
|
26
|
+
on_failure: always # options: [always|never|change] default: always
|
27
|
+
on_start: false # default: false
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 TODO: Write your name
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
[github]: https://github.com/neopoly/rohbau
|
2
|
+
[doc]: http://rubydoc.info/github/neopoly/rohbau/master/file/README.md
|
3
|
+
[gem]: https://rubygems.org/gems/rohbau
|
4
|
+
[gem-badge]: https://img.shields.io/gem/v/rohbau.svg
|
5
|
+
[travis]: https://travis-ci.org/neopoly/rohbau
|
6
|
+
[travis-badge]: https://img.shields.io/travis/neopoly/rohbau.svg?branch=master
|
7
|
+
[codeclimate]: https://codeclimate.com/github/neopoly/rohbau
|
8
|
+
[codeclimate-climate-badge]: https://img.shields.io/codeclimate/github/neopoly/rohbau.svg
|
9
|
+
[codeclimate-coverage-badge]: https://codeclimate.com/github/neopoly/rohbau/badges/coverage.svg
|
10
|
+
[inchpages]: https://inch-ci.org/github/neopoly/rohbau
|
11
|
+
[inchpages-badge]: https://inch-ci.org/github/neopoly/rohbau.svg?branch=master&style=flat
|
12
|
+
|
13
|
+
# Rohbau
|
14
|
+
|
15
|
+
[![Travis][travis-badge]][travis]
|
16
|
+
[![Gem Version][gem-badge]][gem]
|
17
|
+
[![Code Climate][codeclimate-climate-badge]][codeclimate]
|
18
|
+
[![Test Coverage][codeclimate-coverage-badge]][codeclimate]
|
19
|
+
[![Inline docs][inchpages-badge]][inchpages]
|
20
|
+
|
21
|
+
[Gem][gem] |
|
22
|
+
[Source][github] |
|
23
|
+
[Documentation][doc]
|
24
|
+
|
25
|
+
## Description
|
26
|
+
|
27
|
+
Rohbau provides a set of patterns used in Domain Driven Design.
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
gem 'rohbau'
|
34
|
+
|
35
|
+
And then execute:
|
36
|
+
|
37
|
+
$ bundle
|
38
|
+
|
39
|
+
Or install it yourself as:
|
40
|
+
|
41
|
+
$ gem install rohbau
|
42
|
+
|
43
|
+
## Usage
|
44
|
+
|
45
|
+
### Runtime
|
46
|
+
|
47
|
+
By instantiation of the `RuntimeLoader`, an instance of the `Runtime`is created and stored as a singleton.
|
48
|
+
Internal units of the respective component can access this instance by referring to the `RuntimeLoader`.
|
49
|
+
By this a place is made where for example memories for in-memory gateway backend implementations can be stored.
|
50
|
+
|
51
|
+
#### Examples
|
52
|
+
|
53
|
+
Inject a user service to your application
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
require 'rohbau/runtime'
|
57
|
+
require 'rohbau/runtime_loader'
|
58
|
+
|
59
|
+
module MyApplication
|
60
|
+
class RuntimeLoader < Rohbau::RuntimeLoader
|
61
|
+
def initialize
|
62
|
+
super(Runtime)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class Runtime < Rohbau::Runtime
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
module UserService
|
71
|
+
class RuntimeLoader < Rohbau::RuntimeLoader
|
72
|
+
def initialize
|
73
|
+
super(Runtime)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Runtime < Rohbau::Runtime
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Register user service on my application runtime
|
82
|
+
MyApplication::Runtime.register :user_service, UserService::RuntimeLoader
|
83
|
+
MyApplication::Runtime.plugins # => {:user_service=>UserService::RuntimeLoader}
|
84
|
+
|
85
|
+
# Runtimes are not initialized yet
|
86
|
+
MyApplication::RuntimeLoader.instance # => nil
|
87
|
+
MyApplication::Runtime.plugins[:user_service].instance # => nil
|
88
|
+
|
89
|
+
# Boot my application runtime
|
90
|
+
MyApplication::RuntimeLoader.running? # => false
|
91
|
+
MyApplication::RuntimeLoader.new
|
92
|
+
MyApplication::RuntimeLoader.running? # => true
|
93
|
+
|
94
|
+
# Runtimes are initialized
|
95
|
+
MyApplication::RuntimeLoader.instance # => #<MyApplication::Runtime:0x00000000f5b8d8 @user_service=UserService::RuntimeLoader>
|
96
|
+
MyApplication::Runtime.plugins[:user_service].instance # => #<UserService::Runtime:0x00000000b1ecc0>
|
97
|
+
|
98
|
+
# Runtimes are singletons
|
99
|
+
MyApplication::RuntimeLoader.instance === MyApplication::RuntimeLoader.instance
|
100
|
+
MyApplication::Runtime.plugins[:user_service].instance === MyApplication::Runtime.plugins[:user_service].instance
|
101
|
+
|
102
|
+
# Terminate my application runtime
|
103
|
+
MyApplication::RuntimeLoader.terminate
|
104
|
+
MyApplication::RuntimeLoader.running? # => false
|
105
|
+
|
106
|
+
```
|
107
|
+
|
108
|
+
##### Registrar
|
109
|
+
|
110
|
+
Every injected `RuntimeLoader` knows about it's registrar.
|
111
|
+
In the example above `UserService::RuntimeLoader` has been injected to `MyApplication::RuntimeLoader`.
|
112
|
+
`UserService::RuntimeLoader.registrar` therefore returns `MyApplication::RuntimeLoader`.
|
113
|
+
|
114
|
+
##### List of plugins
|
115
|
+
|
116
|
+
Accordingly to the sample above `MyApplication::RuntimeLoader` knows about it's registered plugins.
|
117
|
+
`MyApplication::RuntimeLoader.plugins` therefore returns `{:user_service => UserService::RuntimeLoader}`.
|
118
|
+
|
119
|
+
### ServiceFactory
|
120
|
+
|
121
|
+
The `ServiceFactory` is considered the authority for retrieval of service instances.
|
122
|
+
It follows partly the service locator / registry pattern.
|
123
|
+
|
124
|
+
#### Examples
|
125
|
+
|
126
|
+
Register and unregister default service and override with specific service.
|
127
|
+
|
128
|
+
```ruby
|
129
|
+
require 'rohbau/service_factory'
|
130
|
+
|
131
|
+
MyServiceFactory = Class.new(Rohbau::ServiceFactory)
|
132
|
+
|
133
|
+
user_service_1 = Struct.new(:users).new([:alice, :bob])
|
134
|
+
user_service_2 = Struct.new(:users).new([:jim, :kate])
|
135
|
+
|
136
|
+
runtime = Object.new
|
137
|
+
registry = MyServiceFactory.new(runtime)
|
138
|
+
|
139
|
+
MyServiceFactory.register(:user_service) { user_service_1 }
|
140
|
+
registry.user_service.users # => [:alice, :bob]
|
141
|
+
|
142
|
+
MyServiceFactory.register(:user_service) { user_service_2 }
|
143
|
+
registry.user_service.users # => [:jim, :kate]
|
144
|
+
|
145
|
+
MyServiceFactory.unregister(:user_service)
|
146
|
+
registry.user_service.users # => [:alice, :bob]
|
147
|
+
|
148
|
+
MyServiceFactory.unregister(:user_service)
|
149
|
+
registry.user_service # => NoMethodError: undefined method `user_service'
|
150
|
+
|
151
|
+
```
|
152
|
+
|
153
|
+
Validate registered dependencies
|
154
|
+
|
155
|
+
```ruby
|
156
|
+
MyServiceFactory.external_dependencies :user_service
|
157
|
+
MyServiceFactory.missing_dependencies # => [:user_service]
|
158
|
+
MyServiceFactory.external_dependencies_complied? # => false
|
159
|
+
|
160
|
+
MyServiceFactory.register(:user_service) { Object.new } # => :user_service
|
161
|
+
MyServiceFactory.external_dependencies_complied? # => true
|
162
|
+
MyServiceFactory.missing_dependencies # => []
|
163
|
+
```
|
164
|
+
|
165
|
+
## Build README
|
166
|
+
|
167
|
+
Make changes to README.md.template, not to README.md
|
168
|
+
|
169
|
+
Include examples with
|
170
|
+
|
171
|
+
```bash
|
172
|
+
include_example example_file_name
|
173
|
+
```
|
174
|
+
|
175
|
+
Build README.md with
|
176
|
+
|
177
|
+
```bash
|
178
|
+
./bin/build_readme
|
179
|
+
```
|
180
|
+
|
181
|
+
Always commit README.md.template and README.md together.
|
182
|
+
|
183
|
+
## Contributing
|
184
|
+
|
185
|
+
1. Fork it
|
186
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
187
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
188
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
189
|
+
5. Create new Pull Request
|
data/README.md.template
ADDED
@@ -0,0 +1,119 @@
|
|
1
|
+
[github]: https://github.com/neopoly/rohbau
|
2
|
+
[doc]: http://rubydoc.info/github/neopoly/rohbau/master/file/README.md
|
3
|
+
[gem]: https://rubygems.org/gems/rohbau
|
4
|
+
[gem-badge]: https://img.shields.io/gem/v/rohbau.svg
|
5
|
+
[travis]: https://travis-ci.org/neopoly/rohbau
|
6
|
+
[travis-badge]: https://img.shields.io/travis/neopoly/rohbau.svg?branch=master
|
7
|
+
[codeclimate]: https://codeclimate.com/github/neopoly/rohbau
|
8
|
+
[codeclimate-climate-badge]: https://img.shields.io/codeclimate/github/neopoly/rohbau.svg
|
9
|
+
[codeclimate-coverage-badge]: https://codeclimate.com/github/neopoly/rohbau/badges/coverage.svg
|
10
|
+
[inchpages]: https://inch-ci.org/github/neopoly/rohbau
|
11
|
+
[inchpages-badge]: https://inch-ci.org/github/neopoly/rohbau.svg?branch=master&style=flat
|
12
|
+
|
13
|
+
# Rohbau
|
14
|
+
|
15
|
+
[![Travis][travis-badge]][travis]
|
16
|
+
[![Gem Version][gem-badge]][gem]
|
17
|
+
[![Code Climate][codeclimate-climate-badge]][codeclimate]
|
18
|
+
[![Test Coverage][codeclimate-coverage-badge]][codeclimate]
|
19
|
+
[![Inline docs][inchpages-badge]][inchpages]
|
20
|
+
|
21
|
+
[Gem][gem] |
|
22
|
+
[Source][github] |
|
23
|
+
[Documentation][doc]
|
24
|
+
|
25
|
+
## Description
|
26
|
+
|
27
|
+
Rohbau provides a set of patterns used in Domain Driven Design.
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
gem 'rohbau'
|
34
|
+
|
35
|
+
And then execute:
|
36
|
+
|
37
|
+
$ bundle
|
38
|
+
|
39
|
+
Or install it yourself as:
|
40
|
+
|
41
|
+
$ gem install rohbau
|
42
|
+
|
43
|
+
## Usage
|
44
|
+
|
45
|
+
### Runtime
|
46
|
+
|
47
|
+
By instantiation of the `RuntimeLoader`, an instance of the `Runtime`is created and stored as a singleton.
|
48
|
+
Internal units of the respective component can access this instance by referring to the `RuntimeLoader`.
|
49
|
+
By this a place is made where for example memories for in-memory gateway backend implementations can be stored.
|
50
|
+
|
51
|
+
#### Examples
|
52
|
+
|
53
|
+
Inject a user service to your application
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
include_example runtime
|
57
|
+
```
|
58
|
+
|
59
|
+
##### Registrar
|
60
|
+
|
61
|
+
Every injected `RuntimeLoader` knows about it's registrar.
|
62
|
+
In the example above `UserService::RuntimeLoader` has been injected to `MyApplication::RuntimeLoader`.
|
63
|
+
`UserService::RuntimeLoader.registrar` therefore returns `MyApplication::RuntimeLoader`.
|
64
|
+
|
65
|
+
##### List of plugins
|
66
|
+
|
67
|
+
Accordingly to the sample above `MyApplication::RuntimeLoader` knows about it's registered plugins.
|
68
|
+
`MyApplication::RuntimeLoader.plugins` therefore returns `{:user_service => UserService::RuntimeLoader}`.
|
69
|
+
|
70
|
+
### ServiceFactory
|
71
|
+
|
72
|
+
The `ServiceFactory` is considered the authority for retrieval of service instances.
|
73
|
+
It follows partly the service locator / registry pattern.
|
74
|
+
|
75
|
+
#### Examples
|
76
|
+
|
77
|
+
Register and unregister default service and override with specific service.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
include_example service_factory
|
81
|
+
```
|
82
|
+
|
83
|
+
Validate registered dependencies
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
MyServiceFactory.external_dependencies :user_service
|
87
|
+
MyServiceFactory.missing_dependencies # => [:user_service]
|
88
|
+
MyServiceFactory.external_dependencies_complied? # => false
|
89
|
+
|
90
|
+
MyServiceFactory.register(:user_service) { Object.new } # => :user_service
|
91
|
+
MyServiceFactory.external_dependencies_complied? # => true
|
92
|
+
MyServiceFactory.missing_dependencies # => []
|
93
|
+
```
|
94
|
+
|
95
|
+
## Build README
|
96
|
+
|
97
|
+
Make changes to README.md.template, not to README.md
|
98
|
+
|
99
|
+
Include examples with
|
100
|
+
|
101
|
+
```bash
|
102
|
+
include_example example_file_name
|
103
|
+
```
|
104
|
+
|
105
|
+
Build README.md with
|
106
|
+
|
107
|
+
```bash
|
108
|
+
./bin/build_readme
|
109
|
+
```
|
110
|
+
|
111
|
+
Always commit README.md.template and README.md together.
|
112
|
+
|
113
|
+
## Contributing
|
114
|
+
|
115
|
+
1. Fork it
|
116
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
117
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
118
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
119
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/build_readme
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
cat README.md.template | etc/build_readme.rb > README.md
|
data/etc/build_readme.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
template = $stdin.read
|
4
|
+
examples = template.scan(/include_example (.*)/).flatten
|
5
|
+
|
6
|
+
examples.each do |example|
|
7
|
+
file = "examples/#{example}.rb"
|
8
|
+
if File.exists?(file)
|
9
|
+
replacement = File.read(file)
|
10
|
+
template.gsub!(/include_example #{example}/, replacement)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
$stdout.print template
|
data/examples/runtime.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'rohbau/runtime'
|
2
|
+
require 'rohbau/runtime_loader'
|
3
|
+
|
4
|
+
module MyApplication
|
5
|
+
class RuntimeLoader < Rohbau::RuntimeLoader
|
6
|
+
def initialize
|
7
|
+
super(Runtime)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Runtime < Rohbau::Runtime
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module UserService
|
16
|
+
class RuntimeLoader < Rohbau::RuntimeLoader
|
17
|
+
def initialize
|
18
|
+
super(Runtime)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Runtime < Rohbau::Runtime
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Register user service on my application runtime
|
27
|
+
MyApplication::Runtime.register :user_service, UserService::RuntimeLoader
|
28
|
+
MyApplication::Runtime.plugins # => {:user_service=>UserService::RuntimeLoader}
|
29
|
+
|
30
|
+
# Runtimes are not initialized yet
|
31
|
+
MyApplication::RuntimeLoader.instance # => nil
|
32
|
+
MyApplication::Runtime.plugins[:user_service].instance # => nil
|
33
|
+
|
34
|
+
# Boot my application runtime
|
35
|
+
MyApplication::RuntimeLoader.running? # => false
|
36
|
+
MyApplication::RuntimeLoader.new
|
37
|
+
MyApplication::RuntimeLoader.running? # => true
|
38
|
+
|
39
|
+
# Runtimes are initialized
|
40
|
+
MyApplication::RuntimeLoader.instance # => #<MyApplication::Runtime:0x00000000f5b8d8 @user_service=UserService::RuntimeLoader>
|
41
|
+
MyApplication::Runtime.plugins[:user_service].instance # => #<UserService::Runtime:0x00000000b1ecc0>
|
42
|
+
|
43
|
+
# Runtimes are singletons
|
44
|
+
MyApplication::RuntimeLoader.instance === MyApplication::RuntimeLoader.instance
|
45
|
+
MyApplication::Runtime.plugins[:user_service].instance === MyApplication::Runtime.plugins[:user_service].instance
|
46
|
+
|
47
|
+
# Terminate my application runtime
|
48
|
+
MyApplication::RuntimeLoader.terminate
|
49
|
+
MyApplication::RuntimeLoader.running? # => false
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rohbau/service_factory'
|
2
|
+
|
3
|
+
MyServiceFactory = Class.new(Rohbau::ServiceFactory)
|
4
|
+
|
5
|
+
user_service_1 = Struct.new(:users).new([:alice, :bob])
|
6
|
+
user_service_2 = Struct.new(:users).new([:jim, :kate])
|
7
|
+
|
8
|
+
runtime = Object.new
|
9
|
+
registry = MyServiceFactory.new(runtime)
|
10
|
+
|
11
|
+
MyServiceFactory.register(:user_service) { user_service_1 }
|
12
|
+
registry.user_service.users # => [:alice, :bob]
|
13
|
+
|
14
|
+
MyServiceFactory.register(:user_service) { user_service_2 }
|
15
|
+
registry.user_service.users # => [:jim, :kate]
|
16
|
+
|
17
|
+
MyServiceFactory.unregister(:user_service)
|
18
|
+
registry.user_service.users # => [:alice, :bob]
|
19
|
+
|
20
|
+
MyServiceFactory.unregister(:user_service)
|
21
|
+
registry.user_service # => NoMethodError: undefined method `user_service'
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rohbau/service_factory'
|
2
|
+
|
3
|
+
MyServiceFactory = Class.new(Rohbau::ServiceFactory)
|
4
|
+
|
5
|
+
MyServiceFactory.external_dependencies :user_service
|
6
|
+
MyServiceFactory.missing_dependencies # => [:user_service]
|
7
|
+
MyServiceFactory.external_dependencies_complied? # => false
|
8
|
+
|
9
|
+
MyServiceFactory.register(:user_service) { Object.new } # => :user_service
|
10
|
+
MyServiceFactory.external_dependencies_complied? # => true
|
11
|
+
MyServiceFactory.missing_dependencies # => []
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Rohbau
|
2
|
+
module Application
|
3
|
+
|
4
|
+
class RuntimeWrapper
|
5
|
+
def self.wrap(&constructor)
|
6
|
+
wrapper = Class.new do
|
7
|
+
def self.set_constructor(constructor)
|
8
|
+
@constructor = constructor
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.new(*ignored_args)
|
13
|
+
@constructor.call
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
wrapper.set_constructor(constructor)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_application_runtime(runtime_class)
|
22
|
+
@runtime_class = runtime_class
|
23
|
+
end
|
24
|
+
|
25
|
+
def register_domain(name, namespace)
|
26
|
+
dummy = RuntimeWrapper.wrap do |cls|
|
27
|
+
namespace::Runtime.start
|
28
|
+
end
|
29
|
+
|
30
|
+
@runtime_class.register name, dummy
|
31
|
+
|
32
|
+
domains << namespace
|
33
|
+
end
|
34
|
+
|
35
|
+
def domains
|
36
|
+
@domains ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
def domain_requests
|
40
|
+
domains.map{|d| d.const_get :Request }
|
41
|
+
end
|
42
|
+
|
43
|
+
def use_case_domains
|
44
|
+
domains.select do |domain|
|
45
|
+
domain.const_defined?('UseCases')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def use_cases(use_case_domain = :all)
|
50
|
+
if use_case_domain == :all
|
51
|
+
domains = use_case_domains
|
52
|
+
else
|
53
|
+
domains = [use_case_domain]
|
54
|
+
end
|
55
|
+
|
56
|
+
domains.inject([]) do |use_cases, domain|
|
57
|
+
|
58
|
+
if domain.const_defined?('UseCases')
|
59
|
+
use_case_namespace = domain.const_get('UseCases')
|
60
|
+
use_case_namespace.constants.each do |use_case_class_name|
|
61
|
+
use_cases << use_case_namespace::const_get(use_case_class_name)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
use_cases
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'rohbau/index'
|
2
|
+
|
3
|
+
module Rohbau
|
4
|
+
class DefaultMemoryGateway
|
5
|
+
|
6
|
+
def initialize(memory = Index.new, services = {})
|
7
|
+
@memory = memory
|
8
|
+
@services = services
|
9
|
+
end
|
10
|
+
|
11
|
+
def memory
|
12
|
+
@memory
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(entity)
|
16
|
+
@memory.add entity
|
17
|
+
end
|
18
|
+
|
19
|
+
def bulk_add(*entities)
|
20
|
+
@memory.bulk_add(*entities)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(uid)
|
24
|
+
@memory.get(uid)
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(entity)
|
28
|
+
@memory.update(entity)
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete(uid)
|
32
|
+
@memory.delete(uid)
|
33
|
+
end
|
34
|
+
|
35
|
+
def bulk_delete(*uids)
|
36
|
+
@memory.bulk_delete(*uids)
|
37
|
+
end
|
38
|
+
|
39
|
+
def all
|
40
|
+
@memory.all
|
41
|
+
end
|
42
|
+
|
43
|
+
def size
|
44
|
+
@memory.size
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def service(service_name)
|
50
|
+
@services[service_name] || raise(no_service_error service_name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def no_service_error(service_name)
|
54
|
+
NotImplementedError.new("#{service_name} service in #{self.class}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def map(entity_name, entity)
|
58
|
+
gateway = gateway_for_entity(entity_name)
|
59
|
+
|
60
|
+
if entity.uid
|
61
|
+
result = gateway.update(entity)
|
62
|
+
else
|
63
|
+
result = gateway.add(entity)
|
64
|
+
end
|
65
|
+
|
66
|
+
result.uid
|
67
|
+
end
|
68
|
+
|
69
|
+
def unmap(entity_name, uid)
|
70
|
+
gateway_for_entity(entity_name).get(uid)
|
71
|
+
end
|
72
|
+
|
73
|
+
def gateway_for_entity(entity_name)
|
74
|
+
service(:"#{entity_name}_gateway")
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Rohbau
|
2
|
+
|
3
|
+
class Entity
|
4
|
+
class << self; attr_accessor :__attributes__ end
|
5
|
+
def self.attributes(*attributes)
|
6
|
+
@__attributes__ ||= []
|
7
|
+
@__attributes__ += attributes
|
8
|
+
|
9
|
+
|
10
|
+
predicate_attributes = attributes.select do |attr|
|
11
|
+
attr =~ /\?$/
|
12
|
+
end
|
13
|
+
|
14
|
+
regular_attributes = attributes - predicate_attributes
|
15
|
+
|
16
|
+
predicate_attributes.each do |attribute|
|
17
|
+
attribute_without_predicate = attribute.to_s.gsub(/\?$/, '')
|
18
|
+
attr_accessor attribute_without_predicate
|
19
|
+
|
20
|
+
define_method attribute do ||
|
21
|
+
!!instance_variable_get(:"@#{attribute_without_predicate}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor(*regular_attributes)
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(other)
|
29
|
+
other && __attributes__.all? do |attr|
|
30
|
+
other.respond_to?(attr) &&
|
31
|
+
self.public_send(attr) == other.public_send(attr)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
def __attributes__
|
37
|
+
self.class.__attributes__ || []
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|