enumerated_type 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/README.md +4 -4
- data/lib/enumerated_type.rb +39 -12
- data/lib/enumerated_type/version.rb +1 -1
- data/test/enumerated_type_spec.rb +5 -1
- metadata +5 -19
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
MGRiNTE1NTQ1ZjI5N2IwMGM4ZmVlNjEzYjFhYjNjMGFkNDY1MjdiYQ==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NDM3MDI1NjczOTVmY2E2ZmQwOTQyZWYxMzk5NWFkNTZmNjFlNTdhZQ==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NGU1MjA4OGRkYTU4MDU2MjdlMmI0MjM1NzYwMWRiYTk5Mzg4ZjNiYjgxZjll
|
10
|
+
NDQxNWM1NTA2MjZmYTU4ZmQ5NTJiZjA3Mjk2ZGNlMmUyNGRlYTFhNWU2Njk5
|
11
|
+
MWM1MjM2MDBmNTE0MzQ2YmI5OGYyNmVmNGUyNjQzZWM1ZWQ3N2M=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NDA5MzBmYmNjN2UyMGFlZjA2YTIwYmIzYjVlNjRjMGM2N2YwYjA3ZWFlNDAw
|
14
|
+
ZDk0OTNlYjk3YTRkNDY4NmUwODg0NjIwMDdiODU4YmZiMDFhZjJkZmMwZmE1
|
15
|
+
MjFkYmFjYzg3MDA1MmZlYjhkY2JmYzExM2JhMmYyYTNlNGUzNzI=
|
data/README.md
CHANGED
@@ -36,7 +36,7 @@ if job.status == :failure or job.status == :success
|
|
36
36
|
end
|
37
37
|
```
|
38
38
|
|
39
|
-
At this point,
|
39
|
+
At this point, its starting to feel like a little bit too much knowledge about the `Job` has slipped into other classes; any changes to the in the way status is handled in `Job` will require change in other classes because they've been exposed to the details of its implementation. What, for example, if we want to add another "finished" state that a user should be notified of (say, `:partial_success`)? To deal with this we might create a predicate method that lets you interrogate a `Job` more abstractly about it's status:
|
40
40
|
|
41
41
|
```ruby
|
42
42
|
class Job
|
@@ -47,7 +47,7 @@ class Job
|
|
47
47
|
end
|
48
48
|
```
|
49
49
|
|
50
|
-
Now, say we need another kind of job: the `AdminJob`. It needs to have the same set of statuses (with the same behavior as `Job`'s status). We could certainly move the status related code into a `StatusHaving` module and mix it in to both `Job` and `AdminJob`, but there are some drawbacks here, chief among them that we'd have to add a good bit of coupling between the `Job`, `AdminJob` and the `StatusHaving` mix-in module. For example both classes and the mix-in would need to agree on the `@status` instance variable. I would argue at this point the idea of a `JobStatus` should be promoted to
|
50
|
+
Now, say we need another kind of job: the `AdminJob`. It needs to have the same set of statuses (with the same behavior as `Job`'s status). We could certainly move the status related code into a `StatusHaving` module and mix it in to both `Job` and `AdminJob`, but there are some drawbacks here, chief among them that we'd have to add a good bit of coupling between the `Job`, `AdminJob` and the `StatusHaving` mix-in module. For example both classes and the mix-in would need to agree on the `@status` instance variable. I would argue at this point the idea of a `JobStatus` should be promoted to its own class, maybe with a little bit of error checking:
|
51
51
|
|
52
52
|
```ruby
|
53
53
|
class JobStatus
|
@@ -182,7 +182,7 @@ JobStatus.by(:code, 2) # => #<JobStatus:success>
|
|
182
182
|
JobStatus.by(:code, 4) # => raises a TypeError
|
183
183
|
```
|
184
184
|
|
185
|
-
The first parameter specifies the method that will be called on instances of your `EnumeratedType` during lookup. This works for attributes specified with `declare` (such as `:code` above) but also for
|
185
|
+
The first parameter specifies the method that will be called on instances of your `EnumeratedType` during lookup. This works for attributes specified with `declare` (such as `:code` above) but also for any instance method on your `EnumeratedType`.
|
186
186
|
|
187
187
|
```ruby
|
188
188
|
class JobStatus
|
@@ -193,7 +193,7 @@ end
|
|
193
193
|
|
194
194
|
JobStatus.by(:display, "pending-1") # => #<JobStatus:pending>
|
195
195
|
```
|
196
|
-
If more than one instance of your `EnumeratedType` matches, the first match will be returned in the order the types were `declared`.
|
196
|
+
If more than one instance of your `EnumeratedType` matches, the first match will be returned, in the order the types were `declared`.
|
197
197
|
|
198
198
|
## Development
|
199
199
|
|
data/lib/enumerated_type.rb
CHANGED
@@ -1,9 +1,33 @@
|
|
1
1
|
require "enumerated_type/version"
|
2
2
|
|
3
3
|
module EnumeratedType
|
4
|
+
class ByCache
|
5
|
+
def initialize
|
6
|
+
self.by_property = { }
|
7
|
+
end
|
8
|
+
|
9
|
+
def set(property, value, enumerated)
|
10
|
+
by_value = (by_property[property.to_sym] ||= { })
|
11
|
+
by_value[value] ||= enumerated
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(property, value, miss)
|
15
|
+
by_property.fetch(property.to_sym).fetch(value, &miss)
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_property?(property)
|
19
|
+
by_property.has_key?(property.to_sym)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_accessor :by_property
|
25
|
+
end
|
26
|
+
|
4
27
|
def self.included(base)
|
5
28
|
base.instance_eval do
|
6
29
|
@all = []
|
30
|
+
@by_cache = ByCache.new
|
7
31
|
|
8
32
|
attr_reader :name, :value
|
9
33
|
|
@@ -52,9 +76,14 @@ module EnumeratedType
|
|
52
76
|
@all.each(&block)
|
53
77
|
end
|
54
78
|
|
55
|
-
def by(
|
56
|
-
|
57
|
-
|
79
|
+
def by(property, value, &miss)
|
80
|
+
miss ||= Proc.new { raise(ArgumentError, "Could not find #{self.name} with ##{property} == #{value.inspect}'") }
|
81
|
+
|
82
|
+
if @by_cache.has_property?(property)
|
83
|
+
@by_cache.get(property, value, miss)
|
84
|
+
else
|
85
|
+
find { |e| e.send(property) == value } || miss.call
|
86
|
+
end
|
58
87
|
end
|
59
88
|
|
60
89
|
def [](name)
|
@@ -78,7 +107,7 @@ module EnumeratedType
|
|
78
107
|
private
|
79
108
|
|
80
109
|
def declare(name, options = {})
|
81
|
-
|
110
|
+
unless by(:name, name) { :not_found } == :not_found
|
82
111
|
raise(ArgumentError, "duplicate name #{name.inspect}")
|
83
112
|
end
|
84
113
|
|
@@ -91,18 +120,16 @@ module EnumeratedType
|
|
91
120
|
raise ArgumentError, "Property name 'name' is not allowed (conflicts with default EnumeratedType#name)"
|
92
121
|
end
|
93
122
|
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
|
98
|
-
unless instance_methods.include?(:"#{property}=")
|
99
|
-
attr_writer(:"#{property}")
|
100
|
-
private(:"#{property}=")
|
101
|
-
end
|
123
|
+
attr_accessor(:"#{property}")
|
124
|
+
private(:"#{property}=")
|
102
125
|
end
|
103
126
|
|
104
127
|
enumerated = new(name, options).freeze
|
105
128
|
|
129
|
+
(options.keys + [:name]).each do |property|
|
130
|
+
@by_cache.set(property, enumerated.send(property), enumerated)
|
131
|
+
end
|
132
|
+
|
106
133
|
@all << enumerated
|
107
134
|
const_set(name.to_s.upcase, enumerated)
|
108
135
|
end
|
@@ -190,10 +190,14 @@ describe EnumeratedType do
|
|
190
190
|
Shapes.by(:sides, 4).must_equal(Shapes::RECTANGLE)
|
191
191
|
end
|
192
192
|
|
193
|
-
it "raises an
|
193
|
+
it "raises an argument if there is no match" do
|
194
194
|
lambda { Shapes.by(:sides, 6) }.must_raise(ArgumentError)
|
195
195
|
end
|
196
196
|
|
197
|
+
it "executes (and returns) the block if there is no match" do
|
198
|
+
(Shapes.by(:sides, 6) { "UnknownShape"}).must_equal("UnknownShape")
|
199
|
+
end
|
200
|
+
|
197
201
|
it "returns the first declared value if there is more than one match" do
|
198
202
|
Shapes.by(:pretty_hip, "YEAH").must_equal(Shapes::TRIANGLE)
|
199
203
|
end
|
metadata
CHANGED
@@ -1,20 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: enumerated_type
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.4.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Rafer Hazen
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2014-
|
11
|
+
date: 2014-09-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
17
|
- - ~>
|
20
18
|
- !ruby/object:Gem::Version
|
@@ -22,7 +20,6 @@ dependencies:
|
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
24
|
- - ~>
|
28
25
|
- !ruby/object:Gem::Version
|
@@ -30,7 +27,6 @@ dependencies:
|
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: minitest
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
31
|
- - ~>
|
36
32
|
- !ruby/object:Gem::Version
|
@@ -38,7 +34,6 @@ dependencies:
|
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
38
|
- - ~>
|
44
39
|
- !ruby/object:Gem::Version
|
@@ -46,7 +41,6 @@ dependencies:
|
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rake
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
45
|
- - ~>
|
52
46
|
- !ruby/object:Gem::Version
|
@@ -54,7 +48,6 @@ dependencies:
|
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
52
|
- - ~>
|
60
53
|
- !ruby/object:Gem::Version
|
@@ -78,33 +71,26 @@ files:
|
|
78
71
|
homepage: https://github.com/rafer/enumerated_type
|
79
72
|
licenses:
|
80
73
|
- MIT
|
74
|
+
metadata: {}
|
81
75
|
post_install_message:
|
82
76
|
rdoc_options: []
|
83
77
|
require_paths:
|
84
78
|
- lib
|
85
79
|
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
-
none: false
|
87
80
|
requirements:
|
88
81
|
- - ! '>='
|
89
82
|
- !ruby/object:Gem::Version
|
90
83
|
version: '0'
|
91
|
-
segments:
|
92
|
-
- 0
|
93
|
-
hash: 2282385263752842432
|
94
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
-
none: false
|
96
85
|
requirements:
|
97
86
|
- - ! '>='
|
98
87
|
- !ruby/object:Gem::Version
|
99
88
|
version: '0'
|
100
|
-
segments:
|
101
|
-
- 0
|
102
|
-
hash: 2282385263752842432
|
103
89
|
requirements: []
|
104
90
|
rubyforge_project:
|
105
|
-
rubygems_version:
|
91
|
+
rubygems_version: 2.3.0
|
106
92
|
signing_key:
|
107
|
-
specification_version:
|
93
|
+
specification_version: 4
|
108
94
|
summary: Simple enumerated types
|
109
95
|
test_files:
|
110
96
|
- test/enumerated_type_spec.rb
|