enumerated_type 0.3.0 → 0.4.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 +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
|