fabrique 0.3.1 → 1.0.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 +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
|