fabrique 1.0.0 → 1.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.
- 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:
|