scorpion-ioc 0.1.0 → 0.2.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/README.md +1 -0
- data/lib/scorpion/hunter.rb +5 -5
- data/lib/scorpion/king.rb +69 -31
- data/lib/scorpion/rails/controller.rb +3 -3
- data/lib/scorpion/version.rb +1 -1
- data/lib/scorpion.rb +11 -9
- data/spec/lib/scorpion/hunter_spec.rb +12 -8
- data/spec/lib/scorpion/king_spec.rb +71 -2
- data/spec/lib/scorpion/rails/controller_spec.rb +8 -8
- data/spec/lib/scorpion_spec.rb +36 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e60f46d66df09f4c6f7615fd2710d4fe3527c965
|
4
|
+
data.tar.gz: 57c9523e72aa665056649295c6453c7ce255b724
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 09b2275087d17e93753be0d51c44306b8dc3c18586ab7120821eb5aac16fbdb82b1a9df4ae5a2c67bdb411fe4ea6c629524fdbc2b5bdfd3fdb2d2401552989aa
|
7
|
+
data.tar.gz: 6188ca0ac77ef49985acf0e5d044eec89210d243479ade15d63d6f51289b273ceab9c4ca5f5fe5969353f79082a9d4e4b913341ff8e3c3f04adb1c723d750703
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
[](http://badge.fury.io/rb/scorpion-ioc)
|
4
4
|
[](https://codeclimate.com/github/phallguy/scorpion)
|
5
5
|
[](https://codeclimate.com/github/phallguy/scorpion/coverage)
|
6
|
+
[](https://inch-ci.org/github/phallguy/scorpion)
|
6
7
|
[](https://circleci.com/gh/phallguy/scorpion)
|
7
8
|
|
8
9
|
Add IoC to rails with minimal fuss and ceremony.
|
data/lib/scorpion/hunter.rb
CHANGED
@@ -32,13 +32,13 @@ module Scorpion
|
|
32
32
|
hunting_map.chart &block
|
33
33
|
end
|
34
34
|
|
35
|
-
# @see Scorpion#hunt
|
36
|
-
def hunt_by_traits
|
35
|
+
# @see Scorpion#hunt
|
36
|
+
def hunt_by_traits( contract, traits = nil, *args, &block )
|
37
37
|
unless prey = hunting_map.find( contract, traits )
|
38
|
-
return parent.hunt_by_traits
|
38
|
+
return parent.hunt_by_traits contract, traits if parent
|
39
39
|
|
40
|
-
prey = Scorpion::Prey::ClassPrey.new( contract, nil ) if contract.is_a?( Class ) && traits.
|
41
|
-
unsuccessful_hunt
|
40
|
+
prey = Scorpion::Prey::ClassPrey.new( contract, nil ) if contract.is_a?( Class ) && traits.blank?
|
41
|
+
unsuccessful_hunt( contract, traits ) unless prey
|
42
42
|
end
|
43
43
|
prey.fetch self, *args, &block
|
44
44
|
end
|
data/lib/scorpion/king.rb
CHANGED
@@ -2,7 +2,7 @@ require 'scorpion/attribute_set'
|
|
2
2
|
|
3
3
|
module Scorpion
|
4
4
|
# Identifies objects that are served by {Scorpion scorpions} that feed on
|
5
|
-
# {Scorpion#hunt
|
5
|
+
# {Scorpion#hunt hunted} prey.
|
6
6
|
module King
|
7
7
|
|
8
8
|
# ============================================================================
|
@@ -48,7 +48,7 @@ module Scorpion
|
|
48
48
|
king.instance_variable_set :@scorpion, scorpion
|
49
49
|
# Go hunt for dependencies that are not lazy and initialize the
|
50
50
|
# references.
|
51
|
-
scorpion.feed
|
51
|
+
scorpion.feed king
|
52
52
|
king.send :on_fed
|
53
53
|
end
|
54
54
|
end
|
@@ -76,17 +76,49 @@ module Scorpion
|
|
76
76
|
end
|
77
77
|
|
78
78
|
# Convenience method to ask the {#scorpion} to hunt for an object.
|
79
|
-
# @see Scorpion#hunt
|
80
|
-
def hunt
|
81
|
-
scorpion.hunt
|
79
|
+
# @see Scorpion#hunt
|
80
|
+
def hunt( contract, *args, &block )
|
81
|
+
scorpion.hunt contract, *args, &block
|
82
82
|
end
|
83
83
|
|
84
84
|
# Convenience method to ask the {#scorpion} to hunt for an object.
|
85
|
-
# @see Scorpion#hunt_by_traits
|
86
|
-
def hunt_by_traits
|
87
|
-
scorpion.hunt_by_traits
|
85
|
+
# @see Scorpion#hunt_by_traits
|
86
|
+
def hunt_by_traits( contract, traits, *args, &block )
|
87
|
+
scorpion.hunt_by_traits contract, *args, &block
|
88
88
|
end
|
89
89
|
|
90
|
+
# Feed dependencies from a hash into their associated attributes.
|
91
|
+
# @param [Hash] dependencies hash describing attributes to inject.
|
92
|
+
# @param [Boolean] overwrite existing attributes with values in in the hash.
|
93
|
+
def feast_on( dependencies, overwrite = false )
|
94
|
+
injected_attributes.each do |attr|
|
95
|
+
next unless dependencies.key? attr.name
|
96
|
+
|
97
|
+
if overwrite || !self.send( "#{ attr.name }?" )
|
98
|
+
self.send( "#{ attr.name }=", dependencies[ attr.name ] )
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
dependencies
|
103
|
+
end
|
104
|
+
alias_method :inject_from, :feast_on
|
105
|
+
|
106
|
+
# Injects dependenices from the hash and removes them from the hash.
|
107
|
+
# @see #feast_on
|
108
|
+
def feast_on!( dependencies, overwrite = false )
|
109
|
+
injected_attributes.each do |attr|
|
110
|
+
next unless dependencies.key? attr.name
|
111
|
+
val = dependencies.delete( attr.name )
|
112
|
+
|
113
|
+
if overwrite || !self.send( "#{ attr.name }?" )
|
114
|
+
self.send( "#{ attr.name }=", val )
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
dependencies
|
119
|
+
end
|
120
|
+
alias_method :inject_from!, :feast_on!
|
121
|
+
|
90
122
|
module ClassMethods
|
91
123
|
|
92
124
|
# Tells a {Scorpion} what to inject into the class when it is constructed
|
@@ -113,36 +145,42 @@ module Scorpion
|
|
113
145
|
|
114
146
|
def build_injected_attributes
|
115
147
|
injected_attributes.each do |attr|
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
scorpion.hunt!( attr.contract, attr.traits )
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def #{ attr.name }=( value )
|
125
|
-
@#{ attr.name } = value
|
126
|
-
end
|
148
|
+
build_injected_attribute attr
|
149
|
+
set_injected_attribute_visibility attr
|
150
|
+
end
|
151
|
+
end
|
127
152
|
|
128
|
-
|
129
|
-
|
153
|
+
def build_injected_attribute( attr )
|
154
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
155
|
+
def #{ attr.name }
|
156
|
+
@#{ attr.name } ||= begin
|
157
|
+
attr = injected_attributes[ :#{ attr.name } ]
|
158
|
+
scorpion.hunt( attr.contract, attr.traits )
|
130
159
|
end
|
131
|
-
|
160
|
+
end
|
132
161
|
|
133
|
-
|
134
|
-
|
135
|
-
private :#{ attr.name }=
|
136
|
-
private :#{ attr.name }?
|
137
|
-
RUBY
|
162
|
+
def #{ attr.name }=( value )
|
163
|
+
@#{ attr.name } = value
|
138
164
|
end
|
139
165
|
|
140
|
-
|
141
|
-
|
142
|
-
private :#{ attr.name }
|
143
|
-
RUBY
|
166
|
+
def #{ attr.name }?
|
167
|
+
!!@#{ attr.name }
|
144
168
|
end
|
169
|
+
RUBY
|
170
|
+
end
|
145
171
|
|
172
|
+
def set_injected_attribute_visibility( attr )
|
173
|
+
unless attr.public?
|
174
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
175
|
+
private :#{ attr.name }=
|
176
|
+
private :#{ attr.name }?
|
177
|
+
RUBY
|
178
|
+
end
|
179
|
+
|
180
|
+
if attr.private?
|
181
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
182
|
+
private :#{ attr.name }
|
183
|
+
RUBY
|
146
184
|
end
|
147
185
|
end
|
148
186
|
end
|
@@ -71,14 +71,14 @@ module Scorpion
|
|
71
71
|
end
|
72
72
|
# Allow dependencies to access the current request/response
|
73
73
|
hunter.hunt_for ActionDispatch::Request do |hunter|
|
74
|
-
hunter.hunt
|
74
|
+
hunter.hunt( AbstractController::Base ).request
|
75
75
|
end
|
76
76
|
hunter.hunt_for ActionDispatch::Response do |hunter|
|
77
|
-
hunter.hunt
|
77
|
+
hunter.hunt( AbstractController::Base ).response
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
@scorpion.feed
|
81
|
+
@scorpion.feed self
|
82
82
|
|
83
83
|
yield
|
84
84
|
ensure
|
data/lib/scorpion/version.rb
CHANGED
data/lib/scorpion.rb
CHANGED
@@ -29,25 +29,27 @@ module Scorpion
|
|
29
29
|
# @param [Array<Symbol>] traits required of the prey
|
30
30
|
# @return [Object] an object that matches the requirements defined in `attribute`.
|
31
31
|
# @raise [UnsuccessfulHunt] if a matching object cannot be found.
|
32
|
-
def hunt_by_traits
|
32
|
+
def hunt_by_traits( contract, traits, *args, &block )
|
33
33
|
fail "Not implemented"
|
34
34
|
end
|
35
|
-
alias_method :fetch_by_traits
|
35
|
+
alias_method :fetch_by_traits, :hunt_by_traits
|
36
36
|
|
37
37
|
# Hunts for an object that satisfies the requested `contract` regardless of
|
38
38
|
# traits.
|
39
|
-
# @see #hunt_by_traits
|
40
|
-
def hunt
|
41
|
-
hunt_by_traits
|
39
|
+
# @see #hunt_by_traits
|
40
|
+
def hunt( contract, *args, &block )
|
41
|
+
hunt_by_traits( contract, nil, *args, &block )
|
42
42
|
end
|
43
|
-
alias_method :fetch
|
43
|
+
alias_method :fetch, :hunt
|
44
44
|
|
45
45
|
# Populate given `king` with its expected attributes.
|
46
46
|
# @param [Scorpion::King] king to be fed.
|
47
47
|
# @return [Scorpion::King] the populated king.
|
48
|
-
def feed
|
48
|
+
def feed( king )
|
49
49
|
king.injected_attributes.each do |attr|
|
50
|
-
king.send
|
50
|
+
next if king.send "#{ attr.name }?"
|
51
|
+
|
52
|
+
king.send :feed, attr, hunt_by_traits( attr.contract, attr.traits )
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
@@ -84,7 +86,7 @@ module Scorpion
|
|
84
86
|
|
85
87
|
# Used by concrete scorpions to notify the caller that the hunt was
|
86
88
|
# unsuccessful.
|
87
|
-
def unsuccessful_hunt
|
89
|
+
def unsuccessful_hunt( contract, traits )
|
88
90
|
fail UnsuccessfulHunt.new contract, traits
|
89
91
|
end
|
90
92
|
|
@@ -39,31 +39,35 @@ describe Scorpion::Hunter do
|
|
39
39
|
end
|
40
40
|
|
41
41
|
it "spawns prey" do
|
42
|
-
expect( hunter.hunt
|
42
|
+
expect( hunter.hunt Test::Hunter::Beast ).to be_a Test::Hunter::Bear
|
43
43
|
end
|
44
44
|
|
45
45
|
it "spawns a new instance for multiple requests" do
|
46
|
-
first = hunter.hunt
|
47
|
-
expect( hunter.hunt
|
46
|
+
first = hunter.hunt Test::Hunter::Beast
|
47
|
+
expect( hunter.hunt Test::Hunter::Beast ).not_to eq first
|
48
48
|
end
|
49
49
|
|
50
50
|
it "spawns the same instance for captured prey" do
|
51
|
-
first = hunter.hunt_by_traits
|
52
|
-
expect( hunter.hunt_by_traits
|
51
|
+
first = hunter.hunt_by_traits Test::Hunter::Beast, :tame
|
52
|
+
expect( hunter.hunt_by_traits Test::Hunter::Beast, :tame ).to be first
|
53
53
|
end
|
54
54
|
|
55
55
|
it "injects nested kings" do
|
56
|
-
zoo = hunter.hunt
|
56
|
+
zoo = hunter.hunt Test::Hunter::Zoo
|
57
57
|
expect( zoo.bear ).to be_a Test::Hunter::Bear
|
58
58
|
end
|
59
59
|
|
60
60
|
it "accepts arguments that are passed to constructor" do
|
61
|
-
obj = hunter.hunt
|
61
|
+
obj = hunter.hunt Test::Hunter::Argumented, :awesome
|
62
62
|
expect( obj.arg ).to eq :awesome
|
63
63
|
end
|
64
64
|
|
65
65
|
it "implicitly spawns Class contracts" do
|
66
|
-
expect( hunter.hunt
|
66
|
+
expect( hunter.hunt Test::Hunter::Implicit ).to be_a Test::Hunter::Implicit
|
67
|
+
end
|
68
|
+
|
69
|
+
it "implicitly spawns Class contracts with empty traits" do
|
70
|
+
expect( hunter.hunt_by_traits Test::Hunter::Implicit, [] ).to be_a Test::Hunter::Implicit
|
67
71
|
end
|
68
72
|
|
69
73
|
end
|
@@ -13,7 +13,8 @@ module Test
|
|
13
13
|
def initialize( family, parent = nil, options={}, &block )
|
14
14
|
@family = family
|
15
15
|
@parent = parent
|
16
|
-
@options = options
|
16
|
+
@options = feast_on! options
|
17
|
+
|
17
18
|
|
18
19
|
yield if block_given?
|
19
20
|
end
|
@@ -55,7 +56,7 @@ describe Scorpion::King do
|
|
55
56
|
let( :scorpion ){ double Scorpion }
|
56
57
|
|
57
58
|
before( :each ) do
|
58
|
-
allow( scorpion ).to receive( :feed
|
59
|
+
allow( scorpion ).to receive( :feed )
|
59
60
|
end
|
60
61
|
|
61
62
|
describe ".spawn" do
|
@@ -65,6 +66,11 @@ describe Scorpion::King do
|
|
65
66
|
expect( mamal ).to be_a Test::King::Mamal
|
66
67
|
end
|
67
68
|
|
69
|
+
it "calls feed" do
|
70
|
+
expect( scorpion ).to receive( :feed )
|
71
|
+
Test::King::Mouse.spawn scorpion
|
72
|
+
end
|
73
|
+
|
68
74
|
it "can inherit" do
|
69
75
|
mouse = Test::King::Mouse.spawn scorpion, name: 'name'
|
70
76
|
expect( mouse.family ).to eq 'mouse'
|
@@ -125,5 +131,68 @@ describe Scorpion::King do
|
|
125
131
|
|
126
132
|
end
|
127
133
|
|
134
|
+
describe "feasting" do
|
135
|
+
let( :logger ) { Test::King::Logger.new }
|
136
|
+
let( :options ) { { manager: logger, color: :red } }
|
137
|
+
let( :king ) { Test::King::Mouse.new name: 'mighty' }
|
138
|
+
|
139
|
+
|
140
|
+
describe "#feast_on" do
|
141
|
+
it "assigns attributes" do
|
142
|
+
king.send :feast_on, options
|
143
|
+
expect( king.manager ).to be logger
|
144
|
+
end
|
145
|
+
|
146
|
+
it "doesn't overwrite" do
|
147
|
+
king.manager = Test::King::Logger.new
|
148
|
+
king.send :feast_on, options
|
149
|
+
expect( king.manager ).not_to be logger
|
150
|
+
end
|
151
|
+
|
152
|
+
it "overwrites when asked" do
|
153
|
+
king.manager = Test::King::Logger.new
|
154
|
+
king.send :feast_on, options, true
|
155
|
+
expect( king.manager ).to be logger
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "feast_on!" do
|
160
|
+
it "assigns attributes" do
|
161
|
+
king.send :feast_on!, options
|
162
|
+
expect( king.manager ).to be logger
|
163
|
+
end
|
164
|
+
|
165
|
+
it "doesn't overwrite" do
|
166
|
+
king.manager = Test::King::Logger.new
|
167
|
+
king.send :feast_on!, options
|
168
|
+
expect( king.manager ).not_to be logger
|
169
|
+
end
|
170
|
+
|
171
|
+
it "overwrites when asked" do
|
172
|
+
king.manager = Test::King::Logger.new
|
173
|
+
king.send :feast_on!, options, true
|
174
|
+
expect( king.manager ).to be logger
|
175
|
+
end
|
176
|
+
|
177
|
+
it "removes injected attributes" do
|
178
|
+
expect( options ).to have_key :manager
|
179
|
+
king.send :feast_on!, options
|
180
|
+
expect( options ).not_to have_key :manager
|
181
|
+
end
|
182
|
+
|
183
|
+
it "removes injected attribute even if already set" do
|
184
|
+
expect( options ).to have_key :manager
|
185
|
+
king.manager = Test::King::Logger.new
|
186
|
+
king.send :feast_on!, options
|
187
|
+
expect( options ).not_to have_key :manager
|
188
|
+
end
|
189
|
+
|
190
|
+
it "doesn't remove other options" do
|
191
|
+
king.send :feast_on!, options
|
192
|
+
expect( options ).to have_key :color
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
128
197
|
|
129
198
|
end
|
@@ -18,8 +18,8 @@ describe Scorpion::Rails::Controller, type: :controller do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def index
|
21
|
-
@guard1 = scorpion.hunt
|
22
|
-
@guard2 = scorpion.hunt
|
21
|
+
@guard1 = scorpion.hunt Test::Nest::Guard
|
22
|
+
@guard2 = scorpion.hunt Test::Nest::Guard
|
23
23
|
render nothing: true
|
24
24
|
end
|
25
25
|
end
|
@@ -62,8 +62,8 @@ describe Scorpion::Rails::Controller, type: :controller do
|
|
62
62
|
|
63
63
|
it "spawns the same service during the same request" do
|
64
64
|
allow( subject ).to receive( :index ) do
|
65
|
-
service = subject.
|
66
|
-
expect( subject.scorpion.hunt
|
65
|
+
service = subject.scorpion.hunt Test::Nest::Service
|
66
|
+
expect( subject.scorpion.hunt Test::Nest::Service ).to be service
|
67
67
|
controller.render nothing: true
|
68
68
|
end
|
69
69
|
|
@@ -74,7 +74,7 @@ describe Scorpion::Rails::Controller, type: :controller do
|
|
74
74
|
service = subject.service
|
75
75
|
|
76
76
|
allow( subject ).to receive( :index ) do
|
77
|
-
expect( subject.scorpion.hunt
|
77
|
+
expect( subject.scorpion.hunt Test::Nest::Service ).not_to be service
|
78
78
|
controller.render nothing: true
|
79
79
|
end
|
80
80
|
|
@@ -83,7 +83,7 @@ describe Scorpion::Rails::Controller, type: :controller do
|
|
83
83
|
|
84
84
|
it "hunts for controller" do
|
85
85
|
allow( subject ).to receive( :index ) do
|
86
|
-
expect( subject.scorpion.hunt
|
86
|
+
expect( subject.scorpion.hunt( AbstractController::Base ) ).to be subject
|
87
87
|
controller.render nothing: true
|
88
88
|
end
|
89
89
|
|
@@ -92,7 +92,7 @@ describe Scorpion::Rails::Controller, type: :controller do
|
|
92
92
|
|
93
93
|
it "hunts for response" do
|
94
94
|
allow( subject ).to receive( :index ) do
|
95
|
-
expect( subject.scorpion.hunt
|
95
|
+
expect( subject.scorpion.hunt( ActionDispatch::Response ) ).to be subject.response
|
96
96
|
controller.render nothing: true
|
97
97
|
end
|
98
98
|
|
@@ -101,7 +101,7 @@ describe Scorpion::Rails::Controller, type: :controller do
|
|
101
101
|
|
102
102
|
it "hunts for request" do
|
103
103
|
allow( subject ).to receive( :index ) do
|
104
|
-
expect( subject.scorpion.hunt
|
104
|
+
expect( subject.scorpion.hunt( ActionDispatch::Request ).object_id ).to be subject.request.object_id
|
105
105
|
controller.render nothing: true
|
106
106
|
end
|
107
107
|
|
data/spec/lib/scorpion_spec.rb
CHANGED
@@ -1,4 +1,40 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
module Test
|
4
|
+
module Scorpion
|
5
|
+
class Logger; end
|
6
|
+
|
7
|
+
class Target
|
8
|
+
include ::Scorpion::King
|
9
|
+
|
10
|
+
feed_on do
|
11
|
+
logger Logger, public: true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
3
17
|
describe Scorpion do
|
18
|
+
let( :scorpion ){ Scorpion::Hunter.new }
|
19
|
+
let( :target ) do
|
20
|
+
Test::Scorpion::Target.new.tap do |target|
|
21
|
+
target.instance_variable_set :@scorpion, scorpion
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#feed" do
|
26
|
+
it "injects attributes" do
|
27
|
+
scorpion.feed target
|
28
|
+
|
29
|
+
expect( target.logger ).to be_a Test::Scorpion::Logger
|
30
|
+
end
|
31
|
+
|
32
|
+
it "does not overwrite existing attributes" do
|
33
|
+
logger = Test::Scorpion::Logger.new
|
34
|
+
target.logger = logger
|
35
|
+
scorpion.feed target
|
36
|
+
|
37
|
+
expect( target.logger ).to be logger
|
38
|
+
end
|
39
|
+
end
|
4
40
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scorpion-ioc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Paul Alexander
|
@@ -174,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
174
174
|
version: '0'
|
175
175
|
requirements: []
|
176
176
|
rubyforge_project:
|
177
|
-
rubygems_version: 2.4.
|
177
|
+
rubygems_version: 2.4.6
|
178
178
|
signing_key:
|
179
179
|
specification_version: 4
|
180
180
|
summary: Add IoC to rails with minimal fuss and ceremony
|