enumerated_type 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -195,6 +195,13 @@ JobStatus.by(:display, "pending-1") # => #<JobStatus:pending>
195
195
  ```
196
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
+ If you pass a bock to .by, it will be executed and its value returned (just like Hash#fetch). This is useful for defining a default value or a custom error message.
199
+
200
+ ```ruby
201
+ JobStatus.by(:display, "does-not-exist") { JobStatus::FAILURE } # => #<JobStatus:failure>
202
+ JobStatus.by(:display, "does-not-exist") { |v| raise("I have no idea what to do with #{v.inspect}") } # => raises an exception
203
+ ```
204
+
198
205
  ## Development
199
206
 
200
207
  To run the tests (assuming you have already run `gem install bundler`):
@@ -1,7 +1,29 @@
1
1
  require "enumerated_type/version"
2
2
 
3
3
  module EnumeratedType
4
- class ByCache
4
+ # In the unfortunate case where there are thousands of elements in an
5
+ # enumerated type, an iteration based strategy for EnumeratedType.by is slow.
6
+ # Particularly, since declare does .by(:name, name) to detect name
7
+ # collisions, EnumeratedType.declare is O(n^2) where n is the
8
+ # EnumeratedType.count, which can take seconds when the enunm is loaded,
9
+ # which is, like, a total bummer. This class indexes enums by property and
10
+ # value so lookups are constant time. The backing hash would look like this
11
+ # for the Shape enum.
12
+ #
13
+ # {
14
+ # :sides => {
15
+ # 4 => Shape::Square
16
+ # },
17
+ # :name => {
18
+ # :square => Shape::Square
19
+ # }
20
+ # }
21
+ #
22
+ # Note that there is only a single value for each property/value combination.
23
+ # #set will respect the first instance of a property/value combination (i.e
24
+ # subsequent duplicate #sets will not override the first value). This matches
25
+ # the definition of EnumeratedType.by.
26
+ class PropertyIndex
5
27
  def initialize
6
28
  self.by_property = { }
7
29
  end
@@ -27,7 +49,7 @@ module EnumeratedType
27
49
  def self.included(base)
28
50
  base.instance_eval do
29
51
  @all = []
30
- @by_cache = ByCache.new
52
+ @by_cache = PropertyIndex.new
31
53
 
32
54
  attr_reader :name, :value
33
55
 
@@ -77,12 +99,12 @@ module EnumeratedType
77
99
  end
78
100
 
79
101
  def by(property, value, &miss)
80
- miss ||= Proc.new { raise(ArgumentError, "Could not find #{self.name} with ##{property} == #{value.inspect}'") }
102
+ miss ||= Proc.new { |v| raise(ArgumentError, "Could not find #{self.name} with ##{property} == #{v.inspect}'") }
81
103
 
82
104
  if @by_cache.has_property?(property)
83
105
  @by_cache.get(property, value, miss)
84
106
  else
85
- find { |e| e.send(property) == value } || miss.call
107
+ find { |e| e.send(property) == value } || miss.call(value)
86
108
  end
87
109
  end
88
110
 
@@ -121,6 +143,7 @@ module EnumeratedType
121
143
  end
122
144
 
123
145
  attr_accessor(:"#{property}")
146
+ public(:"#{property}")
124
147
  private(:"#{property}=")
125
148
  end
126
149
 
@@ -1,3 +1,3 @@
1
1
  module EnumeratedType
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -190,7 +190,7 @@ describe EnumeratedType do
190
190
  Shapes.by(:sides, 4).must_equal(Shapes::RECTANGLE)
191
191
  end
192
192
 
193
- it "raises an argument if there is no match" do
193
+ it "raises an argument if there is no match and no block given" do
194
194
  lambda { Shapes.by(:sides, 6) }.must_raise(ArgumentError)
195
195
  end
196
196
 
@@ -198,6 +198,10 @@ describe EnumeratedType do
198
198
  (Shapes.by(:sides, 6) { "UnknownShape"}).must_equal("UnknownShape")
199
199
  end
200
200
 
201
+ it "passes the value to the block" do
202
+ (Shapes.by(:sides, 6) { |sides| "No shape with #{sides} sides" }).must_equal("No shape with 6 sides")
203
+ end
204
+
201
205
  it "returns the first declared value if there is more than one match" do
202
206
  Shapes.by(:pretty_hip, "YEAH").must_equal(Shapes::TRIANGLE)
203
207
  end
@@ -205,6 +209,12 @@ describe EnumeratedType do
205
209
  it "works with arbitrary methods" do
206
210
  Shapes.by(:sides_squared, 16).must_equal(Shapes::RECTANGLE)
207
211
  end
212
+
213
+ it "passes the value to the block for arbitrary methods" do
214
+ (Shapes.by(:sides_squared, 3) { |sides| "No shape with #{sides} sides squared" }).must_equal("No shape with 3 sides squared")
215
+ end
216
+
217
+
208
218
  end
209
219
 
210
220
  describe "#inspect" do
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enumerated_type
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Rafer Hazen
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-09-11 00:00:00.000000000 Z
12
+ date: 2015-07-16 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ~>
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ~>
25
28
  - !ruby/object:Gem::Version
@@ -27,6 +30,7 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: minitest
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - ~>
32
36
  - !ruby/object:Gem::Version
@@ -34,6 +38,7 @@ dependencies:
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ~>
39
44
  - !ruby/object:Gem::Version
@@ -41,6 +46,7 @@ dependencies:
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: rake
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
51
  - - ~>
46
52
  - !ruby/object:Gem::Version
@@ -48,6 +54,7 @@ dependencies:
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
59
  - - ~>
53
60
  - !ruby/object:Gem::Version
@@ -71,26 +78,33 @@ files:
71
78
  homepage: https://github.com/rafer/enumerated_type
72
79
  licenses:
73
80
  - MIT
74
- metadata: {}
75
81
  post_install_message:
76
82
  rdoc_options: []
77
83
  require_paths:
78
84
  - lib
79
85
  required_ruby_version: !ruby/object:Gem::Requirement
86
+ none: false
80
87
  requirements:
81
88
  - - ! '>='
82
89
  - !ruby/object:Gem::Version
83
90
  version: '0'
91
+ segments:
92
+ - 0
93
+ hash: 491884112611942535
84
94
  required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
85
96
  requirements:
86
97
  - - ! '>='
87
98
  - !ruby/object:Gem::Version
88
99
  version: '0'
100
+ segments:
101
+ - 0
102
+ hash: 491884112611942535
89
103
  requirements: []
90
104
  rubyforge_project:
91
- rubygems_version: 2.3.0
105
+ rubygems_version: 1.8.23.2
92
106
  signing_key:
93
- specification_version: 4
107
+ specification_version: 3
94
108
  summary: Simple enumerated types
95
109
  test_files:
96
110
  - test/enumerated_type_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
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=