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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b961bd9747ba8e903c3dfcbc00dcada62acfdd9f
4
- data.tar.gz: 9c101248eb91a7ac3012206b663e7f027624905b
3
+ metadata.gz: 2e300f8bf753f7c3087c94db1a3a94bd41e4964c
4
+ data.tar.gz: 9512f2e6bd7d69d8e76f00fa9eb17a63dfd09d9f
5
5
  SHA512:
6
- metadata.gz: e3a43cad0ac1a58530ee750542d330c7f88515cfb02c0b89e66d580ab98f27ff841b8ae9bd5a44b362df855c2b76c2cf1b449c2af692133add744d07c855f93a
7
- data.tar.gz: 2ce1b6c9abeb2d99cad80249a8e13a846951163d3694bdddf3aa458c9b5dfe223b08dabe57d411907f355cba21ac0a36815c67de3247801fc71c85606d0ebdaa
6
+ metadata.gz: ba6d63d716c3d901a3ef209dce4734707e3084a4213b54457d55712b2bd327375a695eb8b99387b681ab3e2d6d8f3f367a86d8b51be2a839f0711168697354b9
7
+ data.tar.gz: 9a289a742376878ed8337acae369aa2aaf8e2e0597491c31448c17db25c2c9338096bf0425ee3801edf30dfc30761c4b3c0fdcedeac9e9658d4f5ac68bae33ac
data/Gemfile CHANGED
@@ -8,6 +8,6 @@ group :development, :test do
8
8
  end
9
9
 
10
10
  group :devtools do
11
- gem "guard-cucumber", "~> 1.6"
12
- gem "byebug", "~> 6.0"
11
+ gem "guard-cucumber", "~> 2.1"
12
+ gem "byebug", "~> 9.0"
13
13
  end
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", "~> 10.0"
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
@@ -0,0 +1,6 @@
1
+ module Fabrique
2
+
3
+ class MissingBeanError < RuntimeError
4
+ end
5
+
6
+ end
@@ -1,3 +1,3 @@
1
1
  module Fabrique
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
@@ -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.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-06-16 00:00:00.000000000 Z
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: '10.0'
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: '10.0'
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: