deject 0.2.1 → 0.2.2
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.
- data/Readme.md +103 -51
- data/lib/deject/version.rb +1 -1
- metadata +6 -6
data/Readme.md
CHANGED
@@ -16,85 +16,135 @@ On some systems:
|
|
16
16
|
|
17
17
|
If you have to use sudo and you don't know why, it's because you need to set your GEM_HOME environment variable.
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
Examples
|
20
|
+
========
|
21
|
+
|
22
|
+
Add Deject to your class.
|
21
23
|
|
22
24
|
```ruby
|
23
|
-
|
25
|
+
class Game
|
26
|
+
Deject self
|
27
|
+
end
|
28
|
+
```
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
Declare a dependency with a default.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
ComputerPlayer = Class.new
|
34
|
+
|
35
|
+
class Game
|
36
|
+
Deject self
|
37
|
+
dependency(:player) { ComputerPlayer.new }
|
29
38
|
end
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
40
|
+
Game.new.player # => #<ComputerPlayer:0x007fb504945f28>
|
41
|
+
```
|
42
|
+
|
43
|
+
Override the dependency for the class.
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
ComputerPlayer = Class.new
|
47
|
+
HumanPlayer = Class.new
|
48
|
+
|
49
|
+
class Game
|
50
|
+
Deject self
|
51
|
+
dependency(:player) { ComputerPlayer.new }
|
35
52
|
end
|
36
53
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
54
|
+
Game.override(:player) { HumanPlayer.new } # in some initialization file
|
55
|
+
|
56
|
+
Game.new.player # => #<HumanPlayer:0x007fde2d8ac880>
|
57
|
+
```
|
58
|
+
|
59
|
+
Override the dependency for an instance by using `#with_<dependency>`. You can
|
60
|
+
pass a specific object, or a block for lazy initialization. This method returns
|
61
|
+
the instance.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
ComputerPlayer = Class.new
|
65
|
+
HumanPlayer = Class.new
|
66
|
+
MockPlayer = Class.new
|
67
|
+
|
68
|
+
class Game
|
69
|
+
Deject self
|
70
|
+
dependency(:player) { ComputerPlayer.new }
|
41
71
|
end
|
42
72
|
|
73
|
+
Game.new.with_player(HumanPlayer.new).player # => #<HumanPlayer:0x007fb2a1015e40>
|
74
|
+
Game.new.with_player { MockPlayer.new }.player # => #<MockPlayer:0x007fb2a10155f8>
|
75
|
+
```
|
76
|
+
|
77
|
+
Set a global default value to be used when a value isn't explicitly provided.
|
78
|
+
If you are worried about clobbering a previously registered value, invoke with `:player2, safe: true`
|
79
|
+
this is turned off by default because I found that code reloading was horking everything up.
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
ComputerPlayer = Class.new
|
83
|
+
HumanPlayer = Class.new
|
84
|
+
|
85
|
+
# these would go in some initialization file
|
86
|
+
Deject.register(:player1) { ComputerPlayer.new }
|
87
|
+
Deject.register(:player2) { ComputerPlayer.new }
|
88
|
+
|
43
89
|
class Game
|
44
90
|
Deject self
|
45
|
-
dependency(:player1) {
|
91
|
+
dependency(:player1) { HumanPlayer.new }
|
46
92
|
dependency :player2
|
47
|
-
|
48
|
-
def name
|
49
|
-
'poker'
|
50
|
-
end
|
51
93
|
end
|
52
94
|
|
53
|
-
#
|
54
|
-
#
|
55
|
-
|
56
|
-
Deject.register(:player2) { HumanPlayer.new }
|
95
|
+
Game.new.player1 # => #<HumanPlayer:0x007fed8212d7d0>
|
96
|
+
Game.new.player2 # => #<ComputerPlayer:0x007fed8212d348>
|
97
|
+
```
|
57
98
|
|
58
|
-
|
59
|
-
Game.new.player1.type # => "computer player"
|
99
|
+
Dependencies without a default block can passed to the Deject function.
|
60
100
|
|
61
|
-
|
62
|
-
|
101
|
+
```ruby
|
102
|
+
ComputerPlayer = Class.new
|
63
103
|
|
64
|
-
|
65
|
-
|
66
|
-
|
104
|
+
class Game
|
105
|
+
Deject self, :player
|
106
|
+
end
|
67
107
|
|
68
|
-
#
|
69
|
-
|
70
|
-
Game.new.with_player2 { HumanPlayer.new }.player2.type # => "human player"
|
71
|
-
Game.new.with_player2(ComputerPlayer.new).player2.type # => "computer player"
|
108
|
+
Game.new.with_player(ComputerPlayer.new).player # => #<ComputerPlayer:0x007fac2393a248>
|
109
|
+
```
|
72
110
|
|
73
|
-
|
74
|
-
generic_player = Struct.new :type
|
111
|
+
Anywhere a block is used, the instance is passed to it.
|
75
112
|
|
76
|
-
|
77
|
-
|
113
|
+
```ruby
|
114
|
+
ChattyPlayer = Struct.new :message
|
78
115
|
|
79
|
-
Game
|
80
|
-
|
81
|
-
|
116
|
+
class Game < Struct.new(:name)
|
117
|
+
Deject self
|
118
|
+
dependency(:player) { |game| ChattyPlayer.new "You're good at #{game.name}" }
|
119
|
+
end
|
120
|
+
|
121
|
+
player = Game.new('Monopoly').player
|
122
|
+
player.message # => "You're good at Monopoly"
|
82
123
|
|
124
|
+
player = Game.new('Monopoly').with_player { |game| ChattyPlayer.new "You're terrible at #{game.name}" }.player
|
125
|
+
player.message # => "You're terrible at Monopoly"
|
126
|
+
```
|
83
127
|
|
84
|
-
|
128
|
+
Results are memoized.
|
85
129
|
|
86
130
|
```ruby
|
87
|
-
|
88
|
-
|
131
|
+
NamedPlayer = Struct.new :name
|
132
|
+
|
133
|
+
class Game < Struct.new(:name)
|
89
134
|
Deject self
|
90
|
-
dependency :player1
|
91
|
-
dependency :player2
|
92
135
|
|
93
|
-
|
94
|
-
|
136
|
+
i = 0
|
137
|
+
dependency(:player) { NamedPlayer.new "Player#{i+=1}" }
|
95
138
|
end
|
139
|
+
|
140
|
+
game = Game.new
|
141
|
+
game.player.name # => "Player1"
|
142
|
+
game.player.name # => "Player1"
|
143
|
+
|
144
|
+
Game.new.player.name # => "Player2"
|
96
145
|
```
|
97
146
|
|
147
|
+
|
98
148
|
Reasons
|
99
149
|
=======
|
100
150
|
|
@@ -198,7 +248,7 @@ end
|
|
198
248
|
# or the changes that happened to it.
|
199
249
|
```
|
200
250
|
|
201
|
-
Compare to Deject
|
251
|
+
Compare the above examples to Deject
|
202
252
|
|
203
253
|
```ruby
|
204
254
|
class SomeClass
|
@@ -207,6 +257,7 @@ class SomeClass
|
|
207
257
|
end
|
208
258
|
|
209
259
|
# straightforward (no one will be surprised when this changes),
|
260
|
+
# declarative so easy to understand
|
210
261
|
# convenient to override for all instances or any specific instance.
|
211
262
|
```
|
212
263
|
|
@@ -225,11 +276,12 @@ But I couldn't think of a good one. But wait, do I _really_ need a verb? I went
|
|
225
276
|
and decided I was okay with having a method named after the class that applies it, hence `Deject SomeClass`. Not a usual practice
|
226
277
|
but not unheard of, and I don't think it makes sense to force an OO like interface where it doesn't fit well.
|
227
278
|
|
228
|
-
We use `with_<dependency>` instead of `dependency=` because taking blocks is grotesque with assignment methods.
|
279
|
+
We use `with_<dependency>` instead of `dependency=` because taking blocks is grotesque with assignment methods. I have a general
|
229
280
|
disdain for assignment methods as they encourage a mindset that doesn't appreciate the advantages of OO.
|
230
281
|
_"When you have a 'setter' on an object, you have turned an object back into a data structure" -- Alan Kay_.
|
231
282
|
Furthermore, I nearly always want to be able to override the result inline, which you can't easily do with assignment methods
|
232
283
|
as the interpreter guarantees they return the RHS (best solution would be to `tap` the object).
|
284
|
+
The `with_<name>` pattern is a common pattern in [IO](http://iolanguage.com/).
|
233
285
|
|
234
286
|
In general, all variables are stored as locals in closures rather than instance variables on the object. This is
|
235
287
|
partially due to the implementation (alternative implementations used ivars), and partially because I wanted to
|
data/lib/deject/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deject
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70127720072140 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70127720072140
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: pry
|
27
|
-
requirement: &
|
27
|
+
requirement: &70127720071620 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70127720071620
|
36
36
|
description: Provides a super simple API for dependency injection
|
37
37
|
email:
|
38
38
|
- josh.cheek@gmail.com
|