fabrique 0.3.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -2
- data/Gemfile +4 -0
- data/README.md +2 -155
- data/fabrique.gemspec +3 -3
- data/features/bean_factory.feature +194 -3
- data/features/step_definitions/bean_factory_steps.rb +41 -3
- data/features/support/fabrique.rb +1 -0
- data/fixtures/local_only/.gitignore +9 -0
- data/fixtures/local_only/Gemfile +4 -0
- data/fixtures/local_only/README.md +36 -0
- data/fixtures/local_only/Rakefile +2 -0
- data/fixtures/local_only/bin/console +14 -0
- data/fixtures/local_only/bin/setup +8 -0
- data/fixtures/local_only/lib/local_only/version.rb +3 -0
- data/fixtures/local_only/lib/local_only.rb +7 -0
- data/fixtures/local_only/local_only.gemspec +31 -0
- data/fixtures/local_only-0.1.0.gem +0 -0
- data/fixtures/sample/.gitignore +9 -0
- data/fixtures/sample/Gemfile +4 -0
- data/fixtures/sample/README.md +36 -0
- data/fixtures/sample/Rakefile +2 -0
- data/fixtures/sample/bin/console +14 -0
- data/fixtures/sample/bin/setup +8 -0
- data/fixtures/sample/lib/sample/version.rb +3 -0
- data/fixtures/sample/lib/sample.rb +9 -0
- data/fixtures/sample/sample.gemspec +23 -0
- data/lib/fabrique/bean_definition.rb +4 -4
- data/lib/fabrique/bean_definition_registry.rb +11 -5
- data/lib/fabrique/bean_factory.rb +34 -13
- data/lib/fabrique/bean_property_reference.rb +9 -1
- data/lib/fabrique/data_bean.rb +62 -0
- data/lib/fabrique/gem_definition.rb +15 -0
- data/lib/fabrique/gem_dependency_error.rb +6 -0
- data/lib/fabrique/gem_loader.rb +25 -0
- data/lib/fabrique/test/fixtures/constructors.rb +12 -1
- data/lib/fabrique/version.rb +1 -1
- data/lib/fabrique.rb +0 -3
- data/spec/fabrique/data_bean_spec.rb +129 -0
- metadata +32 -38
- data/features/plugin_registry.feature +0 -79
- data/features/step_definitions/plugin_registry_steps.rb +0 -207
- data/lib/fabrique/argument_adaptor/keyword.rb +0 -19
- data/lib/fabrique/argument_adaptor/positional.rb +0 -76
- data/lib/fabrique/construction/as_is.rb +0 -16
- data/lib/fabrique/construction/builder_method.rb +0 -21
- data/lib/fabrique/construction/default.rb +0 -17
- data/lib/fabrique/construction/keyword_argument.rb +0 -16
- data/lib/fabrique/construction/positional_argument.rb +0 -40
- data/lib/fabrique/construction/properties_hash.rb +0 -19
- data/lib/fabrique/constructor/identity.rb +0 -10
- data/lib/fabrique/plugin_registry.rb +0 -56
- data/spec/fabrique/argument_adaptor/keyword_spec.rb +0 -50
- data/spec/fabrique/argument_adaptor/positional_spec.rb +0 -166
- data/spec/fabrique/construction/as_is_spec.rb +0 -23
- data/spec/fabrique/construction/builder_method_spec.rb +0 -29
- data/spec/fabrique/construction/default_spec.rb +0 -19
- data/spec/fabrique/construction/positional_argument_spec.rb +0 -61
- data/spec/fabrique/construction/properties_hash_spec.rb +0 -36
- data/spec/fabrique/constructor/identity_spec.rb +0 -4
- data/spec/fabrique/plugin_registry_spec.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b961bd9747ba8e903c3dfcbc00dcada62acfdd9f
|
4
|
+
data.tar.gz: 9c101248eb91a7ac3012206b663e7f027624905b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3a43cad0ac1a58530ee750542d330c7f88515cfb02c0b89e66d580ab98f27ff841b8ae9bd5a44b362df855c2b76c2cf1b449c2af692133add744d07c855f93a
|
7
|
+
data.tar.gz: 2ce1b6c9abeb2d99cad80249a8e13a846951163d3694bdddf3aa458c9b5dfe223b08dabe57d411907f355cba21ac0a36815c67de3247801fc71c85606d0ebdaa
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -3,6 +3,10 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in fabrique.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
+
group :development, :test do
|
7
|
+
gem "local_only", "~> 0.1.0", path: "fixtures/local_only"
|
8
|
+
end
|
9
|
+
|
6
10
|
group :devtools do
|
7
11
|
gem "guard-cucumber", "~> 1.6"
|
8
12
|
gem "byebug", "~> 6.0"
|
data/README.md
CHANGED
@@ -2,7 +2,8 @@
|
|
2
2
|
|
3
3
|
# Fabrique
|
4
4
|
|
5
|
-
|
5
|
+
Configuration-based factory for dependency injection.
|
6
|
+
Inspired by Java [spring beans](http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html).
|
6
7
|
|
7
8
|
## Installation
|
8
9
|
|
@@ -24,157 +25,3 @@ Or install it yourself as:
|
|
24
25
|
|
25
26
|
Under construction; hard hat required!
|
26
27
|
|
27
|
-
## Puzzling
|
28
|
-
|
29
|
-
However plugin factories are composed, the process of constructing a plugin
|
30
|
-
will be:
|
31
|
-
|
32
|
-
```ruby
|
33
|
-
Properties -> PropertyValidator -> ArgumentAdaptor -> Constructor => plugin`
|
34
|
-
```
|
35
|
-
|
36
|
-
A global function that takes the plugin registration as the composite would
|
37
|
-
then look like this:
|
38
|
-
|
39
|
-
```ruby
|
40
|
-
def fabricate(registry, plugin_identity, properties)
|
41
|
-
registration = registry.find(plugin_identity)
|
42
|
-
property_validator = registration.property_validator
|
43
|
-
argument_adaptor = registration.argument_adaptor
|
44
|
-
constructor = registration.constructor
|
45
|
-
plugin_template = registration.template # Currently called the type
|
46
|
-
|
47
|
-
if property_validator.valid?(properties)
|
48
|
-
arguments = argument_adaptor.adapt(properties)
|
49
|
-
plugin = constructor.construct(plugin_template, arguments)
|
50
|
-
return plugin
|
51
|
-
else
|
52
|
-
raise
|
53
|
-
end
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
So we might compose thus:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
# API gem does this
|
61
|
-
class Store
|
62
|
-
def initialize(provider)
|
63
|
-
@provider = provider
|
64
|
-
end
|
65
|
-
# API definition
|
66
|
-
end
|
67
|
-
StoreApiFactory = Fabrique::FactoryAdaptor.new(
|
68
|
-
template: Store,
|
69
|
-
constructor: Constructor::Classical.new,
|
70
|
-
argument_adaptor: ArgumentAdaptor::Positional.new(:provider)
|
71
|
-
)
|
72
|
-
StoreProviderFactoryRegistry = Fabrique::Registry.new("Store API Provider Registry")
|
73
|
-
|
74
|
-
# Provider gem does this
|
75
|
-
require "store_api"
|
76
|
-
class S3StoreProvider
|
77
|
-
# API implementation here
|
78
|
-
end
|
79
|
-
S3StoreProviderFactory = Fabrique::FactoryAdaptor.new(
|
80
|
-
template: S3StoreProvider,
|
81
|
-
constructor: Constructor::Classical.new,
|
82
|
-
argument_adaptor: ArgumentAdaptor::Keyword.new,
|
83
|
-
)
|
84
|
-
StoreProviderFactoryRegistry.register(:s3, S3StoreProviderFactory)
|
85
|
-
|
86
|
-
# API consumer does this
|
87
|
-
Bundler.require(:default)
|
88
|
-
provider_factory = StoreProviderFactoryRegistry.find(:s3)
|
89
|
-
provider = provider_factory.create(region: "eu-west-1", bucket: "fabrique")
|
90
|
-
api = StoreApiFactory.create(provider: provider)
|
91
|
-
|
92
|
-
# Now, if the API consumer and the API developer agree that this is too high ceremony...
|
93
|
-
|
94
|
-
# API gem adds this
|
95
|
-
class StoreFactory
|
96
|
-
def self.create(provider_id: DEFAULT_PROVIDER, provider_properties: DEFAULT_PROVIDER_PROPERTIES)
|
97
|
-
provider_factory = StoreProviderFactoryRegistry.find(provider_id)
|
98
|
-
provider = provider_factory.create(provider_properties)
|
99
|
-
StoreApiFactory.create(provider: provider)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
# and API consumer just does this
|
104
|
-
Bundler.require(:default)
|
105
|
-
api = StoreFactory.create(provider_id: :s3, provider_properties: {region: "eu-west-1", bucket: "fabrique"})
|
106
|
-
```
|
107
|
-
|
108
|
-
Fabrique might be able to offer an easy way to build the low ceremony "provider
|
109
|
-
API factory". Let's wait and see if high ceremony is really a problem for people.
|
110
|
-
|
111
|
-
### Constructors
|
112
|
-
|
113
|
-
What kinds of construction process do we care about?
|
114
|
-
|
115
|
-
#### Identity
|
116
|
-
|
117
|
-
* Makes no sense to use an ArgumentAdaptor (or, by implication, a
|
118
|
-
PropertyValidator).
|
119
|
-
|
120
|
-
So this is a good pressure to compose everything except Properties
|
121
|
-
into the Constructor, registered by plugin\_identity.
|
122
|
-
|
123
|
-
#### Classical
|
124
|
-
|
125
|
-
* Keywords
|
126
|
-
* Positional
|
127
|
-
* Builder?
|
128
|
-
|
129
|
-
If we say you can mix Classical constructor with Builder ArgumentAdaptor,
|
130
|
-
then the constructor must call a default constructor only (::new()), passing
|
131
|
-
in a block.
|
132
|
-
|
133
|
-
#### Builder
|
134
|
-
|
135
|
-
If we say Builder is a constructor, then it can pass adapted arguments *and*
|
136
|
-
a block to the adapted constructor.
|
137
|
-
|
138
|
-
So, does the world really have constructors that take arguments *and* a
|
139
|
-
builder block?
|
140
|
-
|
141
|
-
#### Lambda?
|
142
|
-
|
143
|
-
This could be used to allow *any* adaptation conceivably supported by the
|
144
|
-
interface of the provider type.
|
145
|
-
|
146
|
-
So, are there adaptations we might want that wouldn't be supported by
|
147
|
-
Identity, Classical and Builder? Yes, surely. But are they *factory*
|
148
|
-
adaptations? Well...
|
149
|
-
|
150
|
-
```ruby
|
151
|
-
class BadlyDesigned
|
152
|
-
def initialize(first_name, last_name)
|
153
|
-
@first_name, @last_name = first_name, last_name
|
154
|
-
end
|
155
|
-
|
156
|
-
def set_title(title)
|
157
|
-
@title = title
|
158
|
-
end
|
159
|
-
|
160
|
-
def address
|
161
|
-
"#{@name} #{@first_name} #{@last_name}"
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
lambda_constructor = ->(type, properties) do
|
166
|
-
type.new(properties).tap { |o| o.set_title(properties[:title]) if properties.include?(:title) }
|
167
|
-
end
|
168
|
-
```
|
169
|
-
|
170
|
-
But are we in the business of adapting badly designed software for use in
|
171
|
-
plugin factories? Should the scope perhaps be to adapt well designed software
|
172
|
-
for use in plugin factories?
|
173
|
-
|
174
|
-
## Contributing
|
175
|
-
|
176
|
-
1. Fork it ( https://github.com/starjuice/fabrique/fork )
|
177
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
178
|
-
3. Commit your changes (`git commit -am 'Add some feature'`)
|
179
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
180
|
-
5. Create a new Pull Request
|
data/fabrique.gemspec
CHANGED
@@ -8,11 +8,11 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Fabrique::VERSION
|
9
9
|
spec.authors = ["Sheldon Hearn"]
|
10
10
|
spec.email = ["sheldonh@starjuice.net"]
|
11
|
-
spec.summary = %q{
|
12
|
-
spec.description = %q{
|
11
|
+
spec.summary = %q{Configuration-based factory for dependency injection}
|
12
|
+
spec.description = %q{Configuration-based factory for dependency injection}
|
13
13
|
spec.homepage = "https://github.com/starjuice/fabrique"
|
14
14
|
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 2.
|
15
|
+
spec.required_ruby_version = ">= 2.1"
|
16
16
|
|
17
17
|
spec.files = `git ls-files -z`.split("\x0")
|
18
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
@@ -79,6 +79,24 @@ Feature: Bean Factory
|
|
79
79
|
And the bean has "color" set to "purple"
|
80
80
|
And the bean has "shape" set to "elephant"
|
81
81
|
|
82
|
+
Scenario: Factory method with bean reference as class
|
83
|
+
|
84
|
+
Given I have a YAML application context definition:
|
85
|
+
"""
|
86
|
+
---
|
87
|
+
beans:
|
88
|
+
- id: factory
|
89
|
+
class: Fabrique::Test::Fixtures::Constructors::FactoryWithCreateMethod
|
90
|
+
- id: created_object
|
91
|
+
class: !bean/ref factory
|
92
|
+
factory_method: create
|
93
|
+
"""
|
94
|
+
When I request a bean factory for the application context
|
95
|
+
And I request the "created_object" bean from the bean factory
|
96
|
+
Then the bean has "size" set to "factory size"
|
97
|
+
And the bean has "color" set to "factory color"
|
98
|
+
And the bean has "shape" set to "factory shape"
|
99
|
+
|
82
100
|
Scenario: Module by identity
|
83
101
|
|
84
102
|
Given I have a YAML application context definition:
|
@@ -142,7 +160,8 @@ Feature: Bean Factory
|
|
142
160
|
properties:
|
143
161
|
shape: !bean/ref left
|
144
162
|
"""
|
145
|
-
|
163
|
+
When I request a bean factory for the application context
|
164
|
+
Then I get a cyclic bean dependency error
|
146
165
|
|
147
166
|
Scenario: Cyclic bean constructor arg reference
|
148
167
|
|
@@ -163,7 +182,8 @@ Feature: Bean Factory
|
|
163
182
|
- purple
|
164
183
|
- elephant
|
165
184
|
"""
|
166
|
-
|
185
|
+
When I request a bean factory for the application context
|
186
|
+
Then I get a cyclic bean dependency error
|
167
187
|
|
168
188
|
Scenario: Cyclic bean property reference with non-cyclic constructor arg reference
|
169
189
|
|
@@ -184,7 +204,25 @@ Feature: Bean Factory
|
|
184
204
|
properties:
|
185
205
|
shape: !bean/ref left
|
186
206
|
"""
|
187
|
-
|
207
|
+
When I request a bean factory for the application context
|
208
|
+
Then I get a cyclic bean dependency error
|
209
|
+
|
210
|
+
Scenario: Cyclic bean class reference
|
211
|
+
|
212
|
+
Given I have a YAML application context definition:
|
213
|
+
"""
|
214
|
+
---
|
215
|
+
beans:
|
216
|
+
- id: factory
|
217
|
+
class: Fabrique::Test::Fixtures::Constructors::FactoryWithCreateMethod
|
218
|
+
constructor_args:
|
219
|
+
- !bean/ref created_object
|
220
|
+
- id: created_object
|
221
|
+
class: !bean/ref factory
|
222
|
+
factory_method: create
|
223
|
+
"""
|
224
|
+
When I request a bean factory for the application context
|
225
|
+
Then I get a cyclic bean dependency error
|
188
226
|
|
189
227
|
Scenario: Nested bean references
|
190
228
|
|
@@ -255,6 +293,35 @@ Feature: Bean Factory
|
|
255
293
|
And the bean has "color" set to "purple"
|
256
294
|
And the bean has "shape" set to "elephant"
|
257
295
|
|
296
|
+
Scenario: Nested bean property reference
|
297
|
+
|
298
|
+
Given I have a YAML application context definition:
|
299
|
+
"""
|
300
|
+
---
|
301
|
+
beans:
|
302
|
+
- id: left
|
303
|
+
class: Fabrique::Test::Fixtures::Constructors::ClassWithPositionalArgumentConstructor
|
304
|
+
constructor_args:
|
305
|
+
- !bean/property_ref middle.object.size
|
306
|
+
- !bean/property_ref middle.object.color
|
307
|
+
- !bean/property_ref middle.object.shape
|
308
|
+
- id: middle
|
309
|
+
class: Fabrique::Test::Fixtures::Constructors::ClassWithProperties
|
310
|
+
properties:
|
311
|
+
object: !bean/ref right
|
312
|
+
- id: right
|
313
|
+
class: Fabrique::Test::Fixtures::Constructors::ClassWithPositionalArgumentConstructor
|
314
|
+
constructor_args:
|
315
|
+
- tiny
|
316
|
+
- purple
|
317
|
+
- elephant
|
318
|
+
"""
|
319
|
+
When I request a bean factory for the application context
|
320
|
+
And I request the "left" bean from the bean factory
|
321
|
+
Then the bean has "size" set to "tiny"
|
322
|
+
And the bean has "color" set to "purple"
|
323
|
+
And the bean has "shape" set to "elephant"
|
324
|
+
|
258
325
|
Scenario: Singleton bean (default)
|
259
326
|
|
260
327
|
Given I have a YAML application context definition:
|
@@ -340,3 +407,127 @@ Feature: Bean Factory
|
|
340
407
|
And the bean has "color" set to "invisible"
|
341
408
|
And the bean has "shape" that is the Integer "42"
|
342
409
|
|
410
|
+
Scenario: Data bean
|
411
|
+
|
412
|
+
Given I have a YAML application context definition:
|
413
|
+
"""
|
414
|
+
---
|
415
|
+
beans:
|
416
|
+
- id: data
|
417
|
+
class: Fabrique::DataBean
|
418
|
+
constructor_args:
|
419
|
+
- size: small
|
420
|
+
color: red
|
421
|
+
shape: dot
|
422
|
+
"""
|
423
|
+
When I request a bean factory for the application context
|
424
|
+
And I request the "data" bean from the bean factory
|
425
|
+
Then the bean has "size" set to "small"
|
426
|
+
And the bean has "color" set to "red"
|
427
|
+
And the bean has "shape" set to "dot"
|
428
|
+
|
429
|
+
Scenario: Gem loader
|
430
|
+
|
431
|
+
Given I have a YAML application context definition:
|
432
|
+
"""
|
433
|
+
---
|
434
|
+
beans:
|
435
|
+
- id: sample
|
436
|
+
class: Sample
|
437
|
+
gem:
|
438
|
+
name: sample
|
439
|
+
version: "= 0.1.1"
|
440
|
+
require: sample
|
441
|
+
factory_method: itself
|
442
|
+
"""
|
443
|
+
And the "sample" gem is not installed
|
444
|
+
When I request a bean factory for the application context
|
445
|
+
And I request that bean dependency gems be loaded for the bean factory
|
446
|
+
And I request the "sample" bean from the bean factory
|
447
|
+
Then the bean has "version" set to "0.1.1"
|
448
|
+
|
449
|
+
Scenario: Gem loader with already-installed gem
|
450
|
+
|
451
|
+
Given I have a YAML application context definition:
|
452
|
+
"""
|
453
|
+
---
|
454
|
+
beans:
|
455
|
+
- id: local_only
|
456
|
+
class: LocalOnly
|
457
|
+
gem:
|
458
|
+
name: local_only
|
459
|
+
version: "= 0.1.0"
|
460
|
+
require: local_only
|
461
|
+
factory_method: itself
|
462
|
+
"""
|
463
|
+
And the "local_only" gem is already installed
|
464
|
+
When I request a bean factory for the application context
|
465
|
+
And I request that bean dependency gems be loaded for the bean factory
|
466
|
+
And I request the "local_only" bean from the bean factory
|
467
|
+
Then the bean has "version" set to "0.1.0"
|
468
|
+
|
469
|
+
Scenario: Gem loader version conflict
|
470
|
+
|
471
|
+
Given I have a YAML application context definition:
|
472
|
+
"""
|
473
|
+
---
|
474
|
+
beans:
|
475
|
+
- id: sample
|
476
|
+
class: Sample
|
477
|
+
gem:
|
478
|
+
name: sample
|
479
|
+
version: "= 0.1.1"
|
480
|
+
require: sample
|
481
|
+
factory_method: itself
|
482
|
+
- id: conflicting_sample
|
483
|
+
class: Sample
|
484
|
+
gem:
|
485
|
+
name: sample
|
486
|
+
version: "= 0.1.0"
|
487
|
+
require: sample
|
488
|
+
factory_method: itself
|
489
|
+
"""
|
490
|
+
And the "sample" gem is not installed
|
491
|
+
When I request a bean factory for the application context
|
492
|
+
And I request that bean dependency gems be loaded for the bean factory
|
493
|
+
Then I get a gem dependency error
|
494
|
+
|
495
|
+
Scenario: Gem loader install error
|
496
|
+
|
497
|
+
Given I have a YAML application context definition:
|
498
|
+
"""
|
499
|
+
---
|
500
|
+
beans:
|
501
|
+
- id: sample
|
502
|
+
class: Sample
|
503
|
+
gem:
|
504
|
+
name: nosuchgeminstallable
|
505
|
+
factory_method: itself
|
506
|
+
"""
|
507
|
+
And the "sample" gem is not installed
|
508
|
+
When I request a bean factory for the application context
|
509
|
+
And I request that bean dependency gems be loaded for the bean factory
|
510
|
+
Then I get a gem dependency error
|
511
|
+
|
512
|
+
Scenario: #to_h
|
513
|
+
|
514
|
+
Given I have a YAML application context definition:
|
515
|
+
"""
|
516
|
+
---
|
517
|
+
beans: !beans
|
518
|
+
- !bean
|
519
|
+
id: square_bean
|
520
|
+
class: Fabrique::Test::Fixtures::Constructors::ClassWithKeywordArgumentConstructor
|
521
|
+
constructor_args:
|
522
|
+
shape: square
|
523
|
+
- !bean
|
524
|
+
id: round_bean
|
525
|
+
class: Fabrique::Test::Fixtures::Constructors::ClassWithKeywordArgumentConstructor
|
526
|
+
constructor_args:
|
527
|
+
shape: round
|
528
|
+
"""
|
529
|
+
When I request a bean factory for the application context
|
530
|
+
And I request a dictionary of all beans
|
531
|
+
Then the dictionary maps "square_bean" to the "square_bean" bean
|
532
|
+
And the dictionary maps "round_bean" to the "round_bean" bean
|
533
|
+
|
@@ -13,7 +13,12 @@ Given(/^I have a YAML application context definition:$/) do |string|
|
|
13
13
|
end
|
14
14
|
|
15
15
|
When(/^I request a bean factory for the application context$/) do
|
16
|
-
|
16
|
+
begin
|
17
|
+
@bean_factory = Fabrique::YamlBeanFactory.new(@tmpfile.path)
|
18
|
+
rescue Exception => e
|
19
|
+
$stderr.puts "DEBUG @bean_factory_request_exception -> #{e.inspect}\n\t#{e.backtrace.join("\n\t")}" if ENV["DEBUG"]
|
20
|
+
@bean_factory_request_exception = e
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
When(/^I request the "(.*?)" bean from the bean factory$/) do |bean_name|
|
@@ -58,8 +63,8 @@ Then(/^I get a different object when I request the "(.*?)" bean again$/) do |bea
|
|
58
63
|
expect(new_reference.object_id).to_not eql @bean.object_id
|
59
64
|
end
|
60
65
|
|
61
|
-
Then(/^I get a cyclic bean dependency error
|
62
|
-
expect
|
66
|
+
Then(/^I get a cyclic bean dependency error$/) do
|
67
|
+
expect(@bean_factory_request_exception).to be_a Fabrique::CyclicBeanDependencyError
|
63
68
|
end
|
64
69
|
|
65
70
|
Then(/^the "(.*?)" and "(.*?)" beans share the same "(.*?)"$/) do |bean1_name, bean2_name, shared_property|
|
@@ -74,3 +79,36 @@ Then(/^the "(.*?)" and "(.*?)" beans each have their own "(.*?)"$/) do |bean1_na
|
|
74
79
|
expect(bean1.send(own_property).object_id).to_not eql bean2.send(own_property).object_id
|
75
80
|
end
|
76
81
|
|
82
|
+
Given(/^the "(.*?)" gem is not installed$/) do |gem|
|
83
|
+
require "rubygems/uninstaller"
|
84
|
+
dep = Gem::Dependency.new(gem, Gem::Requirement.default)
|
85
|
+
specs = dep.matching_specs
|
86
|
+
specs.each do |spec|
|
87
|
+
Gem::Uninstaller.new(spec).uninstall
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Given(/^the "([^"]*)" gem is already installed$/) do |arg1|
|
92
|
+
%x{ gem install --no-ri --no-rdoc fixtures/local_only-0.1.0.gem }
|
93
|
+
end
|
94
|
+
|
95
|
+
When(/^I request that bean dependency gems be loaded for the bean factory$/) do
|
96
|
+
begin
|
97
|
+
@bean_factory.load_gem_dependencies
|
98
|
+
rescue Exception => e
|
99
|
+
$stderr.puts "DEBUG @bean_factory_load_gem_dependencies_exception -> #{e.inspect}\n\t#{e.backtrace.join("\n\t")}" if ENV["DEBUG"]
|
100
|
+
@bean_factory_load_gem_dependencies_exception = e
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
Then(/^I get a gem dependency error$/) do
|
105
|
+
expect(@bean_factory_load_gem_dependencies_exception).to be_a Fabrique::GemDependencyError
|
106
|
+
end
|
107
|
+
|
108
|
+
When(/^I request a dictionary of all beans$/) do
|
109
|
+
@dictionary = @bean_factory.to_h
|
110
|
+
end
|
111
|
+
|
112
|
+
Then(/^the dictionary maps "([^"]*)" to the "([^"]*)" bean$/) do |dictionary_key, bean_name|
|
113
|
+
expect(@dictionary[dictionary_key]).to eql @bean_factory.get_bean(bean_name)
|
114
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "fabrique"
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# LocalOnly
|
2
|
+
|
3
|
+
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/local_only`. To experiment with that code, run `bin/console` for an interactive prompt.
|
4
|
+
|
5
|
+
TODO: Delete this and the text above, and describe your gem
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'local_only'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install local_only
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
TODO: Write usage instructions here
|
26
|
+
|
27
|
+
## Development
|
28
|
+
|
29
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
30
|
+
|
31
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
32
|
+
|
33
|
+
## Contributing
|
34
|
+
|
35
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/local_only.
|
36
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "local_only"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'local_only/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "local_only"
|
8
|
+
spec.version = LocalOnly::VERSION
|
9
|
+
spec.authors = ["Sheldon Hearn"]
|
10
|
+
spec.email = ["sheldonh@starjuice.net"]
|
11
|
+
|
12
|
+
spec.summary = %q{Sample gem that is not avialable from rubygems.org}
|
13
|
+
spec.description = %q{Sample gem that is not avilable from rubygems.org, for testing software that uses gems}
|
14
|
+
spec.homepage = "https://github.com/starjuice/fabrique.git"
|
15
|
+
|
16
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
17
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
18
|
+
if spec.respond_to?(:metadata)
|
19
|
+
spec.metadata['allowed_push_host'] = "http://localhost"
|
20
|
+
else
|
21
|
+
raise "RubyGems 2.0 or newer is required to protect against public gem pushes."
|
22
|
+
end
|
23
|
+
|
24
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
spec.bindir = "exe"
|
26
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
+
spec.require_paths = ["lib"]
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.12"
|
30
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
+
end
|
Binary file
|