jerry 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 +7 -0
- data/.gitignore +38 -0
- data/.rspec +3 -0
- data/.travis.yml +6 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +117 -0
- data/Rakefile +5 -0
- data/jerry.gemspec +25 -0
- data/lib/jerry/config.rb +47 -0
- data/lib/jerry/sugar.rb +41 -0
- data/lib/jerry/version.rb +3 -0
- data/lib/jerry.rb +52 -0
- data/spec/config_spec.rb +64 -0
- data/spec/jerry_spec.rb +132 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/sugar_spec.rb +111 -0
- data/spec/support/silence_warnings.rb +7 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 602f20059904dc280342beeba26963492e75a566
|
4
|
+
data.tar.gz: e41a4ebdb936fa0beee388d153cbb505ba8f6c90
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0a96708a2dc2bf0d3e8ce206e7763760ca08bf1570e58fa5ef8dd12530e03d432ab1bbcd6e4085f2f29efce794bfb236bed57a3bf93bde039849e9be70dc7f38
|
7
|
+
data.tar.gz: 93da221784a25aecda8d98ac356110a791a0b8e7aeca64923a6e7a81b38d2755ce17f34e6cc9c7f217461a19fc8ea62ab5b822a807608033b08c9e0655da8673
|
data/.gitignore
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# Created by http://www.gitignore.io
|
2
|
+
|
3
|
+
### Ruby ###
|
4
|
+
*.gem
|
5
|
+
*.rbc
|
6
|
+
/.config
|
7
|
+
/coverage/
|
8
|
+
/InstalledFiles
|
9
|
+
/pkg/
|
10
|
+
/spec/reports/
|
11
|
+
/test/tmp/
|
12
|
+
/test/version_tmp/
|
13
|
+
/tmp/
|
14
|
+
|
15
|
+
## Specific to RubyMotion:
|
16
|
+
.dat*
|
17
|
+
.repl_history
|
18
|
+
build/
|
19
|
+
|
20
|
+
## Documentation cache and generated files:
|
21
|
+
/.yardoc/
|
22
|
+
/_yardoc/
|
23
|
+
/doc/
|
24
|
+
/rdoc/
|
25
|
+
|
26
|
+
## Environment normalisation:
|
27
|
+
/.bundle/
|
28
|
+
/lib/bundler/man/
|
29
|
+
|
30
|
+
# for a library or gem, you might want to ignore these files since the code is
|
31
|
+
# intended to run in multiple environments; otherwise, check them in:
|
32
|
+
Gemfile.lock
|
33
|
+
.ruby-version
|
34
|
+
.ruby-gemset
|
35
|
+
|
36
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
37
|
+
.rvmrc
|
38
|
+
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Boris Bera
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
Jerry
|
2
|
+
=====
|
3
|
+
|
4
|
+
[](https://travis-ci.org/beraboris/jerry)
|
5
|
+
[](https://coveralls.io/r/beraboris/jerry)
|
6
|
+
|
7
|
+
Jerry rigs your application together. It's an [Inversion of Control](https://en.wikipedia.org/wiki/Inversion_of_control)
|
8
|
+
container for ruby. Just tell Jerry how to build your application and it will set it all up for you.
|
9
|
+
|
10
|
+
Installation
|
11
|
+
============
|
12
|
+
|
13
|
+
The usual stuff. Either
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'jerry'
|
17
|
+
```
|
18
|
+
|
19
|
+
then
|
20
|
+
|
21
|
+
$ bundle install
|
22
|
+
|
23
|
+
or
|
24
|
+
|
25
|
+
$ gem install jerry
|
26
|
+
|
27
|
+
Usage
|
28
|
+
=====
|
29
|
+
|
30
|
+
Let's say you have the following code:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
class Window; end
|
34
|
+
class Door; end
|
35
|
+
|
36
|
+
class House
|
37
|
+
attr_reader :window, :door
|
38
|
+
|
39
|
+
def initialize(window, door)
|
40
|
+
@window = window
|
41
|
+
@door = door
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
First, require jerry:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
require 'jerry'
|
50
|
+
```
|
51
|
+
|
52
|
+
Then, define a config class. This class tells jerry how to construct your application.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
class MyConfig < Jerry::Config
|
56
|
+
component(:window) { Window.new }
|
57
|
+
component(:door) { Door.new }
|
58
|
+
component(:house) { House.new rig(:window), rig(:door) }
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
The `component` method defines a component. Usually you'll want a component per class. The `rig` method tells jerry to
|
63
|
+
build a component.
|
64
|
+
|
65
|
+
Finally, when you want to build your application, ask jerry to do it for you.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
jerry = Jerry.new MyConfig.new
|
69
|
+
house = jerry.rig :house
|
70
|
+
```
|
71
|
+
|
72
|
+
Scopes
|
73
|
+
------
|
74
|
+
|
75
|
+
The `component` method lets you specify a scope. The scope can either be `:single` or `:instance` and the default is
|
76
|
+
`:single`. If you set the scope to `:single` only one instance of the component will be created. If you set it to
|
77
|
+
`:instance`, a new instance of the component will be created each time you call `rig`.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
class MyConfig < Jerry::Config
|
81
|
+
component(:window, scope: :instance) { Window.new }
|
82
|
+
component(:door, scope: :single) { Door.new }
|
83
|
+
end
|
84
|
+
jerry = Jerry.new MyConfig.new
|
85
|
+
|
86
|
+
window_a = jerry.rig :window
|
87
|
+
window_b = jerry.rig :window
|
88
|
+
window_a.object_id == window_b.object_id
|
89
|
+
#=> false
|
90
|
+
|
91
|
+
door_a = jerry.rig :door
|
92
|
+
door_b = jerry.rig :door
|
93
|
+
door_a.object_id == door_b.object_id
|
94
|
+
#=> true
|
95
|
+
```
|
96
|
+
|
97
|
+
Multiple configs
|
98
|
+
----------------
|
99
|
+
|
100
|
+
Jerry lets you use multiple configs. This way you can organize your configs however you want. You can pass multiple
|
101
|
+
configs to `Jerry.new` or you can use `jerry << SomeConfig.new` to add configs to jerry.
|
102
|
+
|
103
|
+
If two configs define the same component, the config that was inserted last will have priority. With `Jerry.new`, the
|
104
|
+
later arguments have priority.
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
class ConfA < Jerry::Config
|
108
|
+
component(:thing) { "from a" }
|
109
|
+
end
|
110
|
+
class ConfB < Jerry::Config
|
111
|
+
component(:thing) { "from b" }
|
112
|
+
end
|
113
|
+
jerry = Jerry.new ConfA.new, ConfB.new
|
114
|
+
|
115
|
+
jerry.rig :thing
|
116
|
+
#=> "from b"
|
117
|
+
```
|
data/Rakefile
ADDED
data/jerry.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'jerry/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'jerry'
|
8
|
+
spec.version = Jerry::VERSION
|
9
|
+
spec.authors = ['Boris Bera']
|
10
|
+
spec.email = ['bboris@rsoft.ca']
|
11
|
+
spec.summary = %q{Jerry rigs your application together. It's an Inversion of Control container.}
|
12
|
+
spec.description = %q{Jerry is an Inversion of Control container. It allows you to decouple the code that bootstraps your application from the rest of your application}
|
13
|
+
spec.homepage = 'http://github.com/beraboris/jerry'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0.0'
|
24
|
+
spec.add_development_dependency 'yard', '~> 0.8.7.4'
|
25
|
+
end
|
data/lib/jerry/config.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'jerry/sugar'
|
2
|
+
|
3
|
+
class Jerry
|
4
|
+
# Base class for all jerry configs.
|
5
|
+
#
|
6
|
+
# It defines all of the instance methods for a config
|
7
|
+
#
|
8
|
+
# @abstract Subclass to define a config
|
9
|
+
# @example
|
10
|
+
# class MyConfig < Jerry::Config
|
11
|
+
# component(:service) { MyService.new }
|
12
|
+
# component(:app) { MyApp.new rig(:service) }
|
13
|
+
# end
|
14
|
+
# @see Jerry::Sugar injected class methods
|
15
|
+
class Config
|
16
|
+
# Injects Jerry::Sugar into inherited classes
|
17
|
+
def self.inherited(subclass)
|
18
|
+
subclass.send :extend, Jerry::Sugar
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Array<Symbol>] list of components defined by the config
|
22
|
+
def components
|
23
|
+
self.class.components
|
24
|
+
end
|
25
|
+
|
26
|
+
# Jerry instance the config is part of
|
27
|
+
#
|
28
|
+
# This gets set by Jerry when it loads a config
|
29
|
+
attr_writer :jerry
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
# Creates a component
|
34
|
+
def rig(component)
|
35
|
+
@jerry.rig component
|
36
|
+
end
|
37
|
+
|
38
|
+
# Check if given component exists
|
39
|
+
def knows?(component)
|
40
|
+
@jerry.knows? component
|
41
|
+
end
|
42
|
+
|
43
|
+
def cache
|
44
|
+
@cache ||= {}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/jerry/sugar.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
class Jerry
|
2
|
+
class ComponentError < StandardError; end
|
3
|
+
|
4
|
+
# Contains all the class helper methods that are injected when you inherit from Jerry::Config
|
5
|
+
module Sugar
|
6
|
+
# @return [Array<Symbol>] list of the components defined by the config
|
7
|
+
def components
|
8
|
+
@components ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
# Defines a component
|
12
|
+
#
|
13
|
+
# @param [Symbol] name name of the component
|
14
|
+
# @param [Hash] options options hash see supported options
|
15
|
+
# @option options [Symbol] (:single) The scope of the component. Can be either :single or :instance.
|
16
|
+
# When the scope is :single, only one instance of the component will be created and every call
|
17
|
+
# to Jerry#rig will return the same instance. When the scope is :instance, every call to Jerry#rig
|
18
|
+
# will return a new instance.
|
19
|
+
# @yield Block used to instantiate the component. This block in only called when Jerry#rig is called.
|
20
|
+
# @raise [Jerry::ComponentError] when the block is missing or the scope is invalid
|
21
|
+
def component(name, options={}, &block)
|
22
|
+
raise Jerry::ComponentError, "could not define component #{name}, block is missing" if block.nil?
|
23
|
+
|
24
|
+
scope = options[:scope] || :single
|
25
|
+
unless [:single, :instance].include? scope
|
26
|
+
raise Jerry::ComponentError, "could not define component #{name}, scope #{scope} is unknown"
|
27
|
+
end
|
28
|
+
|
29
|
+
define_method name do
|
30
|
+
case scope
|
31
|
+
when :single
|
32
|
+
cache[name] ||= instance_eval(&block)
|
33
|
+
when :instance
|
34
|
+
instance_eval(&block)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
components << name
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/jerry.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'jerry/version'
|
2
|
+
require 'jerry/config'
|
3
|
+
|
4
|
+
# Inversion of Control container.
|
5
|
+
#
|
6
|
+
# This class is in charge of bootstrapping your application. This is done by defining {Jerry::Config configs}.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# class MyConfig < Jerry::Config
|
10
|
+
# component(:app) { MyApp.new }
|
11
|
+
# end
|
12
|
+
# jerry = Jerry.new MyConfig.new
|
13
|
+
# jerry.rig :app #=> #<MyApp:...>
|
14
|
+
class Jerry
|
15
|
+
class RigError < StandardError; end
|
16
|
+
|
17
|
+
# @param [Jerry::Config] configs Configs used to rig components. Multiple config can be given. If two configs
|
18
|
+
# define the same component, the later one will have priority.
|
19
|
+
def initialize(*configs)
|
20
|
+
@index = {}
|
21
|
+
|
22
|
+
configs.each { |config| self << config }
|
23
|
+
end
|
24
|
+
|
25
|
+
# Load a config
|
26
|
+
#
|
27
|
+
# @param [Jerry::Config] config Config to be loaded. If the loaded config defines a component already defined
|
28
|
+
# by another config, the component from the new config will take priority.
|
29
|
+
def <<(config)
|
30
|
+
components = config.components
|
31
|
+
components.each { |component| @index[component] = config }
|
32
|
+
config.jerry = self
|
33
|
+
end
|
34
|
+
|
35
|
+
# Rigs a component
|
36
|
+
#
|
37
|
+
# @param [Symbol] component Component to rig.
|
38
|
+
# @return The component requested
|
39
|
+
# @raise [Jerry::RigError] when the requested component does not exist
|
40
|
+
def rig(component)
|
41
|
+
raise RigError, "could not find component #{component}" unless knows? component
|
42
|
+
|
43
|
+
@index[component].public_send component
|
44
|
+
end
|
45
|
+
|
46
|
+
# Checks if a component exists
|
47
|
+
#
|
48
|
+
# @param [Symbol] component component to check
|
49
|
+
def knows?(component)
|
50
|
+
@index.has_key? component
|
51
|
+
end
|
52
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'jerry/config'
|
3
|
+
|
4
|
+
describe Jerry::Config do
|
5
|
+
let(:klass) {Class.new(Jerry::Config)}
|
6
|
+
|
7
|
+
it 'should extend the its subclass with Jerry::Sugar when inherited' do
|
8
|
+
expect(klass.singleton_class.included_modules).to include Jerry::Sugar
|
9
|
+
expect(klass).to respond_to :components
|
10
|
+
expect(klass).to respond_to :component
|
11
|
+
end
|
12
|
+
|
13
|
+
describe '#components' do
|
14
|
+
it 'should call the class contents method' do
|
15
|
+
instance = klass.new
|
16
|
+
|
17
|
+
expect(klass).to receive(:components).and_return([:something])
|
18
|
+
|
19
|
+
expect(instance.components).to eq([:something])
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#rig' do
|
24
|
+
it 'should call rig on the previously set jerry' do
|
25
|
+
jerry = double('jerry')
|
26
|
+
config = klass.new
|
27
|
+
config.jerry = jerry
|
28
|
+
|
29
|
+
expect(jerry).to receive(:rig).with(:target)
|
30
|
+
|
31
|
+
config.instance_eval { rig :target }
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should return the result from the jerry rig method' do
|
35
|
+
jerry = double('jerry')
|
36
|
+
allow(jerry).to receive(:rig).with(anything).and_return 42
|
37
|
+
config = klass.new
|
38
|
+
config.jerry = jerry
|
39
|
+
|
40
|
+
expect(config.instance_eval { rig :something }).to eq(42)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#knows?' do
|
45
|
+
it 'should call the knows? method on the previously set jerry' do
|
46
|
+
jerry = double('jerry')
|
47
|
+
config = klass.new
|
48
|
+
config.jerry = jerry
|
49
|
+
|
50
|
+
expect(jerry).to receive(:knows?).with(:target)
|
51
|
+
|
52
|
+
config.instance_eval { knows? :target }
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'should return the results from the jerry knows? method' do
|
56
|
+
jerry = double('jerry')
|
57
|
+
allow(jerry).to receive(:knows?).with(anything).and_return true
|
58
|
+
config = klass.new
|
59
|
+
config.jerry = jerry
|
60
|
+
|
61
|
+
expect(config.instance_eval { knows? :something }).to be_truthy
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/spec/jerry_spec.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'jerry'
|
3
|
+
|
4
|
+
describe Jerry do
|
5
|
+
it 'should work with all the pieces' do
|
6
|
+
house = Class.new do
|
7
|
+
attr_reader :window, :door
|
8
|
+
|
9
|
+
def initialize(window, door)
|
10
|
+
@window = window
|
11
|
+
@door = door
|
12
|
+
end
|
13
|
+
end
|
14
|
+
window = Class.new
|
15
|
+
door = Class.new
|
16
|
+
|
17
|
+
config = Class.new(Jerry::Config) do
|
18
|
+
component(:window) { window.new }
|
19
|
+
component(:door) { door.new }
|
20
|
+
component(:house) {
|
21
|
+
house.new rig(:window), rig(:door)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
jerry = Jerry.new config.new
|
25
|
+
|
26
|
+
instance = jerry.rig :house
|
27
|
+
|
28
|
+
expect(instance).not_to be_nil
|
29
|
+
expect(instance).to be_a house
|
30
|
+
expect(instance.window).not_to be_nil
|
31
|
+
expect(instance.window).to be_a window
|
32
|
+
expect(instance.door).not_to be_nil
|
33
|
+
expect(instance.door).to be_a door
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#rig' do
|
37
|
+
it 'should raise error if the component does not exist' do
|
38
|
+
jerry = Jerry.new
|
39
|
+
|
40
|
+
expect{jerry.rig :not_actually_a_thing}.to raise_error(Jerry::RigError)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should call the component method on the config' do
|
44
|
+
config = double('config', components: [:doomsday_device]).as_null_object
|
45
|
+
jerry = Jerry.new config
|
46
|
+
|
47
|
+
expect(config).to receive(:doomsday_device).with(no_args)
|
48
|
+
|
49
|
+
jerry.rig :doomsday_device
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should call the component method registered last' do
|
53
|
+
target = double('target')
|
54
|
+
jerry = Jerry.new double('old config', components: [:target]).as_null_object,
|
55
|
+
double('new config', components: [:target], target: target).as_null_object
|
56
|
+
|
57
|
+
component = jerry.rig :target
|
58
|
+
|
59
|
+
expect(component).to eq(target)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#<<' do
|
64
|
+
let(:jerry) { Jerry.new }
|
65
|
+
|
66
|
+
it 'should fetch the config components' do
|
67
|
+
config = double('config').as_null_object
|
68
|
+
|
69
|
+
expect(config).to receive(:components).and_return([])
|
70
|
+
|
71
|
+
jerry << config
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'should register components' do
|
75
|
+
config = double('config', components: [:target]).as_null_object
|
76
|
+
|
77
|
+
jerry << config
|
78
|
+
|
79
|
+
expect(jerry.knows? :target).to be_truthy
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should overwrite previous components' do
|
83
|
+
target = double('target')
|
84
|
+
config = double('config', components: [:target], target: target).as_null_object
|
85
|
+
|
86
|
+
jerry << config
|
87
|
+
|
88
|
+
expect(jerry.rig :target).to eq(target)
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should pass an instance of itself to the config' do
|
92
|
+
config = double('config', components: []).as_null_object
|
93
|
+
|
94
|
+
expect(config).to receive(:jerry=).with(jerry)
|
95
|
+
|
96
|
+
jerry << config
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#knows?' do
|
101
|
+
it 'should be true when the component is defined by a config' do
|
102
|
+
jerry = Jerry.new double('config', components: [:target]).as_null_object
|
103
|
+
|
104
|
+
expect(jerry.knows? :target).to be_truthy
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should be false if the component is defined by no config' do
|
108
|
+
jerry = Jerry.new double('config', components: [:not_target]).as_null_object
|
109
|
+
|
110
|
+
expect(jerry.knows? :target).to be_falsey
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#initialize' do
|
115
|
+
it 'should register all the config components' do
|
116
|
+
configs = 'a'.upto('c').map {|i| double("config #{i}", components: [i.to_sym]).as_null_object}
|
117
|
+
jerry = Jerry.new(*configs)
|
118
|
+
|
119
|
+
expect(jerry.knows? :a).to be_truthy
|
120
|
+
expect(jerry.knows? :b).to be_truthy
|
121
|
+
expect(jerry.knows? :c).to be_truthy
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should give priority to the components of later configs' do
|
125
|
+
target = double('target')
|
126
|
+
jerry = Jerry.new double('old config', components: [:target]).as_null_object,
|
127
|
+
double('new config', components: [:target], target: target).as_null_object
|
128
|
+
|
129
|
+
expect(jerry.rig :target).to eq(target)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
|
2
|
+
|
3
|
+
silence_warnings do
|
4
|
+
require 'coveralls'
|
5
|
+
Coveralls.wear!
|
6
|
+
end
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.order = :random
|
10
|
+
Kernel.srand config.seed
|
11
|
+
|
12
|
+
config.expect_with :rspec do |expectations|
|
13
|
+
expectations.syntax = :expect
|
14
|
+
end
|
15
|
+
|
16
|
+
config.mock_with :rspec do |mocks|
|
17
|
+
mocks.syntax = :expect
|
18
|
+
mocks.verify_partial_doubles = true
|
19
|
+
end
|
20
|
+
end
|
data/spec/sugar_spec.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'rspec'
|
2
|
+
require 'jerry/config'
|
3
|
+
|
4
|
+
describe Jerry::Sugar do
|
5
|
+
let(:sugar) {Class.new Jerry::Config}
|
6
|
+
|
7
|
+
describe '#component' do
|
8
|
+
it 'should create a method with the given name' do
|
9
|
+
sugar.component(:my_component) {}
|
10
|
+
|
11
|
+
expect(sugar.new).to respond_to(:my_component)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should add the name to the list of components' do
|
15
|
+
sugar.component(:target) {}
|
16
|
+
|
17
|
+
expect(sugar.components).to include(:target)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should raise an error when scope is unknown' do
|
21
|
+
expect{sugar.component(:target, scope: :not_a_thing) {}}.to raise_error(Jerry::ComponentError)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should raise an error when block is missing' do
|
25
|
+
expect{sugar.component :target}.to raise_error(Jerry::ComponentError)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'defined method' do
|
29
|
+
it 'should have the right self set' do
|
30
|
+
sugar.component(:_self) { self }
|
31
|
+
instance = sugar.new
|
32
|
+
|
33
|
+
expect(instance._self).not_to be_a Class
|
34
|
+
expect(instance._self).to be_a sugar
|
35
|
+
expect(instance._self).to eq(instance)
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'with scope set to :single' do
|
39
|
+
it 'should only call the block once' do
|
40
|
+
call_count = 0
|
41
|
+
sugar.component(:target, scope: :single) {call_count += 1}
|
42
|
+
instance = sugar.new
|
43
|
+
|
44
|
+
3.times {instance.target}
|
45
|
+
|
46
|
+
expect(call_count).to eq(1)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should keep returning the first created component' do
|
50
|
+
call_count = 0
|
51
|
+
sugar.component(:target, scope: :single) {call_count += 1}
|
52
|
+
instance = sugar.new
|
53
|
+
|
54
|
+
expect(instance.target).to eq(1)
|
55
|
+
expect(instance.target).to eq(1)
|
56
|
+
expect(instance.target).to eq(1)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with scope set to :instance' do
|
61
|
+
it 'should call the block every time' do
|
62
|
+
call_count = 0
|
63
|
+
sugar.component(:target, scope: :instance) {call_count += 1}
|
64
|
+
instance = sugar.new
|
65
|
+
|
66
|
+
3.times {instance.target}
|
67
|
+
|
68
|
+
expect(call_count).to eq(3)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'should return a new instance every time' do
|
72
|
+
call_count = 0
|
73
|
+
sugar.component(:target, scope: :instance) {call_count += 1}
|
74
|
+
instance = sugar.new
|
75
|
+
|
76
|
+
expect(instance.target).to eq(1)
|
77
|
+
expect(instance.target).to eq(2)
|
78
|
+
expect(instance.target).to eq(3)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context 'with no scope' do
|
83
|
+
it 'should only call the block once' do
|
84
|
+
call_count = 0
|
85
|
+
sugar.component(:target) {call_count += 1}
|
86
|
+
instance = sugar.new
|
87
|
+
|
88
|
+
3.times {instance.target}
|
89
|
+
|
90
|
+
expect(call_count).to eq(1)
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'should keep returning the first created component' do
|
94
|
+
call_count = 0
|
95
|
+
sugar.component(:target) {call_count += 1}
|
96
|
+
instance = sugar.new
|
97
|
+
|
98
|
+
expect(instance.target).to eq(1)
|
99
|
+
expect(instance.target).to eq(1)
|
100
|
+
expect(instance.target).to eq(1)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#components' do
|
107
|
+
it 'should default to an empty array' do
|
108
|
+
expect(sugar.components).to eq([])
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jerry
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Boris Bera
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-06-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 3.0.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 3.0.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yard
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.8.7.4
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.8.7.4
|
69
|
+
description: Jerry is an Inversion of Control container. It allows you to decouple
|
70
|
+
the code that bootstraps your application from the rest of your application
|
71
|
+
email:
|
72
|
+
- bboris@rsoft.ca
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- ".rspec"
|
79
|
+
- ".travis.yml"
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE.txt
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- jerry.gemspec
|
85
|
+
- lib/jerry.rb
|
86
|
+
- lib/jerry/config.rb
|
87
|
+
- lib/jerry/sugar.rb
|
88
|
+
- lib/jerry/version.rb
|
89
|
+
- spec/config_spec.rb
|
90
|
+
- spec/jerry_spec.rb
|
91
|
+
- spec/spec_helper.rb
|
92
|
+
- spec/sugar_spec.rb
|
93
|
+
- spec/support/silence_warnings.rb
|
94
|
+
homepage: http://github.com/beraboris/jerry
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.2.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Jerry rigs your application together. It's an Inversion of Control container.
|
118
|
+
test_files:
|
119
|
+
- spec/config_spec.rb
|
120
|
+
- spec/jerry_spec.rb
|
121
|
+
- spec/spec_helper.rb
|
122
|
+
- spec/sugar_spec.rb
|
123
|
+
- spec/support/silence_warnings.rb
|
124
|
+
has_rdoc:
|