scorpion-ioc 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/scorpion-ioc.svg)](http://badge.fury.io/rb/scorpion-ioc)
|
4
4
|
[![Code Climate](https://codeclimate.com/github/phallguy/scorpion.png)](https://codeclimate.com/github/phallguy/scorpion)
|
5
5
|
[![Test Coverage](https://codeclimate.com/github/phallguy/scorpion/badges/coverage.svg)](https://codeclimate.com/github/phallguy/scorpion/coverage)
|
6
|
+
[![Inch CI](https://inch-ci.org/github/phallguy/scorpion.svg?branch=master)](https://inch-ci.org/github/phallguy/scorpion)
|
6
7
|
[![Circle CI](https://circleci.com/gh/phallguy/scorpion.svg?style=svg)](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
|