fabrique 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -2
- data/README.md +97 -0
- data/fabrique.gemspec +1 -1
- data/features/bean_factory.feature +32 -0
- data/lib/fabrique/bean_definition_registry.rb +2 -1
- data/lib/fabrique/missing_bean_error.rb +6 -0
- data/lib/fabrique/version.rb +1 -1
- data/spec/fabrique/bean_factory_spec.rb +12 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e300f8bf753f7c3087c94db1a3a94bd41e4964c
|
4
|
+
data.tar.gz: 9512f2e6bd7d69d8e76f00fa9eb17a63dfd09d9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba6d63d716c3d901a3ef209dce4734707e3084a4213b54457d55712b2bd327375a695eb8b99387b681ab3e2d6d8f3f367a86d8b51be2a839f0711168697354b9
|
7
|
+
data.tar.gz: 9a289a742376878ed8337acae369aa2aaf8e2e0597491c31448c17db25c2c9338096bf0425ee3801edf30dfc30761c4b3c0fdcedeac9e9658d4f5ac68bae33ac
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -21,7 +21,104 @@ Or install it yourself as:
|
|
21
21
|
|
22
22
|
$ gem install fabrique
|
23
23
|
|
24
|
+
## Testing
|
25
|
+
|
26
|
+
```shell
|
27
|
+
git clone git@github.com/starjuice/fabrique.git
|
28
|
+
cd fabrique
|
29
|
+
bundle
|
30
|
+
bundle exec rake
|
31
|
+
```
|
32
|
+
|
33
|
+
The test coverage is superficial at the moment. When working with features/bean_factory.feature,
|
34
|
+
keep in mind that some exceptions are caught and stored as instance variables to be evlauated by
|
35
|
+
subsequent steps. This avoids some English contortions, but the down side is that if you introduce
|
36
|
+
a regression that raises an exception in a scenario that doesn't expect one, you won't see the
|
37
|
+
exception. To log exceptions, even when they are expected:
|
38
|
+
|
39
|
+
```shell
|
40
|
+
DEBUG=1 bundle exec rake
|
41
|
+
```
|
42
|
+
|
24
43
|
## Usage
|
25
44
|
|
26
45
|
Under construction; hard hat required!
|
27
46
|
|
47
|
+
The best source of documentation of what's possible in the configuration of Fabrique::BeanFactory is currently
|
48
|
+
features/bean\_factory.feature. But reading the step definitions for an example of usage would be awkward, so
|
49
|
+
here is a code example.
|
50
|
+
|
51
|
+
Given this example YAML application context definition,
|
52
|
+
in a file called application\_context.yml:
|
53
|
+
|
54
|
+
```yaml
|
55
|
+
---
|
56
|
+
beans:
|
57
|
+
- id: customer_repository
|
58
|
+
class: Acme::Repository::CustomerRepository
|
59
|
+
constructor_args:
|
60
|
+
- !bean/ref store
|
61
|
+
- !bean/ref customer_data_mapper
|
62
|
+
- id: product_repository
|
63
|
+
class: Acme::Repository::ProductRepository
|
64
|
+
constructor_args:
|
65
|
+
store: !bean/ref store
|
66
|
+
data_mapper: !bean/ref product_data_mapper
|
67
|
+
- id: store
|
68
|
+
class: Acme::Repository::MysqlStore
|
69
|
+
constructor_args:
|
70
|
+
host: localhost
|
71
|
+
port: 3306
|
72
|
+
gem:
|
73
|
+
name: acme-repository-mysql_store
|
74
|
+
version: "~> 1.0"
|
75
|
+
require: "acme/repository/mysql_store"
|
76
|
+
- id: customer_data_mapper
|
77
|
+
class: Acme::Repository::MysqlDataMapper::Customer
|
78
|
+
gem:
|
79
|
+
name: acme-repository-mysql_data_mapper
|
80
|
+
require: acme/repository/mysql_data_mapper/customer
|
81
|
+
- id: product_data_mapper
|
82
|
+
class: Acme::Repository::MysqlDataMapper::Product
|
83
|
+
gem:
|
84
|
+
name: acme-repository-mysql_data_mapper
|
85
|
+
require: acme/repository/mysql_data_mapper/product
|
86
|
+
```
|
87
|
+
|
88
|
+
Here is how we could materialize these dependencies:
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
bean_factory = Fabrique::YamlBeanFactory.new(File.read('application_context.yml'))
|
92
|
+
bean_factory.load_gem_dependencies
|
93
|
+
|
94
|
+
customer_service = CustomerService.new(repository: bean_factory.get_bean('customer_repository'))
|
95
|
+
product_service = ProductService.new(repository: bean_factory.get_bean('product_repository'))
|
96
|
+
store_service = StoreService.new(customers: customer_service, products: product_service)
|
97
|
+
# ...
|
98
|
+
```
|
99
|
+
|
100
|
+
Of course, the construction of these services could just as well have been handled by the
|
101
|
+
bean factory as well. Where to draw the line is an interesting topic. The example above draws it
|
102
|
+
"at dependencies that could be expected to vary per deployment".
|
103
|
+
|
104
|
+
Notice that gems were only specified for the parts of the context that could be expected to
|
105
|
+
vary per deployment; the gem providing Acme::Repository::CustomerRepository and
|
106
|
+
Acme::Repository::ProductRepository would be bundled with the application.
|
107
|
+
|
108
|
+
Also notice that the gem loader is activated by an explicit call to load\_gem\_dependencies.
|
109
|
+
Runtime installation and activation of gems is controversial, and so it must be requested
|
110
|
+
explicitly.
|
111
|
+
|
112
|
+
For a data-centric approach to IoC, the entire set of beans can be materialized as a dictionary
|
113
|
+
and made available to consumer to cherry-pick what they need without any awareness of the use
|
114
|
+
of a BeanFactory:
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
bean_factory = Fabrique::YamlBeanFactory.new('application_context.yml')
|
118
|
+
bean_factory.load_gem_dependencies
|
119
|
+
|
120
|
+
# Symbolize keys for use as keyword arguments:
|
121
|
+
context = bean_factory.to_h.map { |k, v| [k.intern, v] }.to_h
|
122
|
+
|
123
|
+
store_service = StoreService.new(context)
|
124
|
+
```
|
data/fabrique.gemspec
CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
22
|
spec.add_development_dependency "bundler", "~> 1.7"
|
23
|
-
spec.add_development_dependency "rake", "~>
|
23
|
+
spec.add_development_dependency "rake", "~> 11.0"
|
24
24
|
spec.add_development_dependency "rspec", "~> 3.2"
|
25
25
|
spec.add_development_dependency "cucumber", "~> 2.0"
|
26
26
|
end
|
@@ -466,6 +466,38 @@ Feature: Bean Factory
|
|
466
466
|
And I request the "local_only" bean from the bean factory
|
467
467
|
Then the bean has "version" set to "0.1.0"
|
468
468
|
|
469
|
+
Scenario: Gem loader with duplicate gem
|
470
|
+
|
471
|
+
Given I have a YAML application context definition:
|
472
|
+
"""
|
473
|
+
---
|
474
|
+
beans:
|
475
|
+
- id: sampler
|
476
|
+
class: Fabrique::DataBean
|
477
|
+
constructor_args:
|
478
|
+
- sample1_version: !bean/property_ref sample1.version
|
479
|
+
sample2_version: !bean/property_ref sample2.version
|
480
|
+
- id: sample1
|
481
|
+
class: Sample
|
482
|
+
gem:
|
483
|
+
name: sample
|
484
|
+
version: "= 0.1.1"
|
485
|
+
require: sample
|
486
|
+
factory_method: itself
|
487
|
+
- id: sample2
|
488
|
+
class: Sample
|
489
|
+
gem:
|
490
|
+
name: sample
|
491
|
+
require: sample
|
492
|
+
factory_method: itself
|
493
|
+
"""
|
494
|
+
And the "sample" gem is not installed
|
495
|
+
When I request a bean factory for the application context
|
496
|
+
And I request that bean dependency gems be loaded for the bean factory
|
497
|
+
And I request the "sampler" bean from the bean factory
|
498
|
+
Then the bean has "sample1_version" set to "0.1.1"
|
499
|
+
And the bean has "sample2_version" set to "0.1.1"
|
500
|
+
|
469
501
|
Scenario: Gem loader version conflict
|
470
502
|
|
471
503
|
Given I have a YAML application context definition:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "tsort"
|
2
2
|
require_relative "bean_definition"
|
3
3
|
require_relative "cyclic_bean_dependency_error"
|
4
|
+
require_relative "missing_bean_error"
|
4
5
|
|
5
6
|
module Fabrique
|
6
7
|
|
@@ -12,7 +13,7 @@ module Fabrique
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def get_definition(bean_name)
|
15
|
-
@defs.detect { |d| d.id == bean_name }
|
16
|
+
@defs.detect { |d| d.id == bean_name } or raise MissingBeanError.new("missing bean #{bean_name.inspect}")
|
16
17
|
end
|
17
18
|
|
18
19
|
def get_definitions
|
data/lib/fabrique/version.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Fabrique::BeanFactory do
|
4
|
+
|
5
|
+
it "raises a missing bean error when asked for a nonexistent bean" do
|
6
|
+
bean_factory = Fabrique::BeanFactory.new(Fabrique::BeanDefinitionRegistry.new([]))
|
7
|
+
expect {
|
8
|
+
bean_factory.get_bean("nonexistent")
|
9
|
+
}.to raise_error Fabrique::MissingBeanError, /nonexistent/
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fabrique
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sheldon Hearn
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '11.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '11.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- lib/fabrique/gem_definition.rb
|
123
123
|
- lib/fabrique/gem_dependency_error.rb
|
124
124
|
- lib/fabrique/gem_loader.rb
|
125
|
+
- lib/fabrique/missing_bean_error.rb
|
125
126
|
- lib/fabrique/test.rb
|
126
127
|
- lib/fabrique/test/fixtures/constructors.rb
|
127
128
|
- lib/fabrique/test/fixtures/modules.rb
|
@@ -129,6 +130,7 @@ files:
|
|
129
130
|
- lib/fabrique/test/fixtures/repository.rb
|
130
131
|
- lib/fabrique/version.rb
|
131
132
|
- lib/fabrique/yaml_bean_factory.rb
|
133
|
+
- spec/fabrique/bean_factory_spec.rb
|
132
134
|
- spec/fabrique/data_bean_spec.rb
|
133
135
|
- spec/fabrique/yaml_bean_factory_spec.rb
|
134
136
|
- spec/fabrique_spec.rb
|
@@ -162,7 +164,9 @@ test_files:
|
|
162
164
|
- features/step_definitions/bean_factory_steps.rb
|
163
165
|
- features/support/byebug.rb
|
164
166
|
- features/support/fabrique.rb
|
167
|
+
- spec/fabrique/bean_factory_spec.rb
|
165
168
|
- spec/fabrique/data_bean_spec.rb
|
166
169
|
- spec/fabrique/yaml_bean_factory_spec.rb
|
167
170
|
- spec/fabrique_spec.rb
|
168
171
|
- spec/spec_helper.rb
|
172
|
+
has_rdoc:
|