typesafe_enum 0.1.8 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +206 -28
- data/.idea/.rakeTasks +7 -0
- data/.idea/codeStyles/Project.xml +45 -0
- data/.idea/codeStyles/codeStyleConfig.xml +5 -0
- data/.idea/go.imports.xml +6 -0
- data/.idea/inspectionProfiles/Project_Default.xml +17 -0
- data/.idea/misc.xml +9 -0
- data/.idea/modules.xml +8 -0
- data/.idea/typesafe_enum.iml +38 -0
- data/.idea/vcs.xml +6 -0
- data/.rubocop.yml +247 -12
- data/.ruby-version +1 -1
- data/.travis.yml +7 -0
- data/CHANGES.md +23 -0
- data/README.md +49 -20
- data/lib/typesafe_enum.rb +1 -1
- data/lib/typesafe_enum/base.rb +36 -30
- data/lib/typesafe_enum/module_info.rb +2 -2
- data/spec/.rubocop.yml +8 -5
- data/spec/unit/typesafe_enum/base_spec.rb +107 -24
- data/typesafe_enum.gemspec +10 -12
- metadata +36 -36
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.6
|
data/.travis.yml
CHANGED
data/CHANGES.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## 0.3.0
|
2
|
+
|
3
|
+
- Support explicit nil values
|
4
|
+
- Update author email in gemspec
|
5
|
+
- Update RuboCop to version 0.91 and pin version
|
6
|
+
- Set minimum required_ruby_version to 2.6.0
|
7
|
+
- Bump .ruby-version to 2.6.6
|
8
|
+
|
9
|
+
## 0.2.2 (23 April 2020)
|
10
|
+
|
11
|
+
- Implement [`Enumerable`](https://ruby-doc.org/core-2.6.5/Enumerable.html)
|
12
|
+
|
13
|
+
## 0.2.1 (12 March 2020)
|
14
|
+
|
15
|
+
- Update to Rake 12.3.3
|
16
|
+
|
17
|
+
## 0.2.0 (12 March 2020)
|
18
|
+
|
19
|
+
- Update to Ruby 2.6.5
|
20
|
+
- Update to Rake 10.4
|
21
|
+
- Update to RSpec 3.9
|
22
|
+
- Update to RuboCop 0.80
|
23
|
+
|
1
24
|
## 0.1.8 (22 December 2017)
|
2
25
|
|
3
26
|
- Update to Ruby 2.4.1
|
data/README.md
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# TypesafeEnum
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/
|
4
|
-
[![Code Climate](https://codeclimate.com/github/
|
5
|
-
[![Inline docs](http://inch-ci.org/github/
|
6
|
-
[![Gem Version](https://img.shields.io/gem/v/typesafe_enum.svg)](https://github.com/
|
3
|
+
[![Build Status](https://travis-ci.org/dmolesUC/typesafe_enum.svg?branch=master)](https://travis-ci.org/dmolesUC/typesafe_enum)
|
4
|
+
[![Code Climate](https://codeclimate.com/github/dmolesUC/typesafe_enum.svg)](https://codeclimate.com/github/dmolesUC/typesafe_enum)
|
5
|
+
[![Inline docs](http://inch-ci.org/github/dmolesUC/typesafe_enum.svg)](http://inch-ci.org/github/dmolesUC/typesafe_enum)
|
6
|
+
[![Gem Version](https://img.shields.io/gem/v/typesafe_enum.svg)](https://github.com/dmolesUC/typesafe_enum/releases)
|
7
7
|
|
8
8
|
A Ruby implementation of Joshua Bloch's
|
9
9
|
[typesafe enum pattern](http://www.oracle.com/technetwork/java/page1-139488.html#replaceenums),
|
@@ -14,23 +14,25 @@ with syntax loosely inspired by [Ruby::Enum](https://github.com/dblock/ruby-enum
|
|
14
14
|
- [Basic usage](#basic-usage)
|
15
15
|
- [Ordering](#ordering)
|
16
16
|
- [String representations](#string-representations)
|
17
|
+
- [Enumerable](#enumerable)
|
17
18
|
- [Convenience methods on enum classes](#convenience-methods-on-enum-classes)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
- [#to_a](#to_a)
|
20
|
+
- [#size](#size)
|
21
|
+
- [#each, <code>#each_with_index</code>, <code>#map</code> and <code>#flat_map</code>](#each-each_with_index-map-and-flat_map)
|
22
|
+
- [#find_by_key, <code>#find_by_value</code>, <code>#find_by_ord</code>](#find_by_key-find_by_value-find_by_ord)
|
23
|
+
- [#find_by_value_str](#find_by_value_str)
|
23
24
|
- [Enum classes with methods](#enum-classes-with-methods)
|
24
25
|
- [Enum instances with methods](#enum-instances-with-methods)
|
25
|
-
- [How is this different from Ruby::Enum
|
26
|
+
- [How is this different from <a href="https://github.com/dblock/ruby-enum">Ruby::Enum</a>?](#how-is-this-different-from-rubyenum)
|
26
27
|
- [How is this different from java.lang.Enum?](#how-is-this-different-from-javalangenum)
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
- [Clunkier syntax](#clunkier-syntax)
|
29
|
+
- [No special switch/<code>case</code> support](#no-special-switchcase-support)
|
30
|
+
- [No serialization support](#no-serialization-support)
|
31
|
+
- [No support classes](#no-support-classes)
|
32
|
+
- [Enum classes are not closed](#enum-classes-are-not-closed)
|
32
33
|
- [Contributing](#contributing)
|
33
34
|
|
35
|
+
|
34
36
|
## Basic usage
|
35
37
|
|
36
38
|
Create a new enum class and a set of instances:
|
@@ -91,6 +93,20 @@ Scale::KILO.value
|
|
91
93
|
# => 1000
|
92
94
|
```
|
93
95
|
|
96
|
+
Even `nil` is a valid value (if set explicitly):
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
class Scheme < TypesafeEnum::Base
|
100
|
+
new :HTTP, 'http'
|
101
|
+
new :HTTPS, 'https'
|
102
|
+
new :EXAMPLE, 'example'
|
103
|
+
new :UNKNOWN, nil
|
104
|
+
end
|
105
|
+
|
106
|
+
Scheme::UNKNOWN.value
|
107
|
+
# => nil
|
108
|
+
```
|
109
|
+
|
94
110
|
Declaring two instances with the same key will produce an error:
|
95
111
|
|
96
112
|
```ruby
|
@@ -199,9 +215,19 @@ Suit::DIAMONDS.to_s
|
|
199
215
|
|
200
216
|
It can of course be overridden.
|
201
217
|
|
218
|
+
## `Enumerable`
|
219
|
+
|
220
|
+
As of version 0.2.2, `TypesafeEnum` classes implement
|
221
|
+
[`Enumerable`](https://ruby-doc.org/core-2.6.5/Enumerable.html),
|
222
|
+
so they support methods such as
|
223
|
+
[`#find`](https://ruby-doc.org/core-2.6.5/Enumerable.html#method-i-find),
|
224
|
+
[`#select`](https://ruby-doc.org/core-2.6.5/Enumerable.html#method-i-select),
|
225
|
+
and [`#reduce`](https://ruby-doc.org/core-2.6.5/Enumerable.html#method-i-reduce),
|
226
|
+
in addition to the convenience methods called out specifically below.
|
227
|
+
|
202
228
|
## Convenience methods on enum classes
|
203
229
|
|
204
|
-
###
|
230
|
+
### `#to_a`
|
205
231
|
|
206
232
|
Returns an array of the enum instances in declaration order:
|
207
233
|
|
@@ -210,7 +236,7 @@ Tarot.to_a
|
|
210
236
|
# => [#<Tarot:0x007fd4db30eca8 @key=:CUPS, @value="Cups", @ord=0>, #<Tarot:0x007fd4db30ebe0 @key=:COINS, @value="Coins", @ord=1>, #<Tarot:0x007fd4db30eaf0 @key=:WANDS, @value="Wands", @ord=2>, #<Tarot:0x007fd4db30e9b0 @key=:SWORDS, @value="Swords", @ord=3>]
|
211
237
|
```
|
212
238
|
|
213
|
-
###
|
239
|
+
### `#size`
|
214
240
|
|
215
241
|
Returns the number of enum instances:
|
216
242
|
|
@@ -219,7 +245,7 @@ Suit.size
|
|
219
245
|
# => 4
|
220
246
|
```
|
221
247
|
|
222
|
-
###
|
248
|
+
### `#each`, `#each_with_index`, `#map` and `#flat_map`
|
223
249
|
|
224
250
|
Iterate over the set of enum instances:
|
225
251
|
|
@@ -238,9 +264,12 @@ Suit.each_with_index { |s, i| puts "#{i}: #{s.key}" }
|
|
238
264
|
|
239
265
|
Suit.map(&:value)
|
240
266
|
# => ["clubs", "diamonds", "hearts", "spades"]
|
267
|
+
|
268
|
+
Suit.flat_map { |s| [s.key, s.value] }
|
269
|
+
# => [:CLUBS, "clubs", :DIAMONDS, "diamonds", :HEARTS, "hearts", :SPADES, "spades"]
|
241
270
|
```
|
242
271
|
|
243
|
-
###
|
272
|
+
### `#find_by_key`, `#find_by_value`, `#find_by_ord`
|
244
273
|
|
245
274
|
Look up an enum instance based on its key, value, or ordinal:
|
246
275
|
|
@@ -253,7 +282,7 @@ Tarot.find_by_ord(3)
|
|
253
282
|
# => #<Tarot:0x007faab19fd810 @key=:SWORDS, @value="Swords", @ord=3>
|
254
283
|
```
|
255
284
|
|
256
|
-
###
|
285
|
+
### `#find_by_value_str`
|
257
286
|
|
258
287
|
Look up an enum instance based on the string form of its value (as returned by `to_s`) --
|
259
288
|
useful for, e.g., XML or JSON mapping of enums with non-string values:
|
data/lib/typesafe_enum.rb
CHANGED
data/lib/typesafe_enum/base.rb
CHANGED
@@ -8,6 +8,7 @@ module TypesafeEnum
|
|
8
8
|
include Comparable
|
9
9
|
|
10
10
|
class << self
|
11
|
+
include Enumerable
|
11
12
|
|
12
13
|
# Returns an array of the enum instances in declaration order
|
13
14
|
# @return [Array<self>] All instances of this enum, in declaration order
|
@@ -18,32 +19,16 @@ module TypesafeEnum
|
|
18
19
|
# Returns the number of enum instances
|
19
20
|
# @return [Integer] the number of instances
|
20
21
|
def size
|
21
|
-
as_array
|
22
|
+
as_array.size
|
22
23
|
end
|
23
24
|
|
24
25
|
# Iterates over the set of enum instances
|
25
26
|
# @yield [self] Each instance of this enum, in declaration order
|
26
|
-
# @return [
|
27
|
+
# @return [Enumerator<self>] All instances of this enum, in declaration order
|
27
28
|
def each(&block)
|
28
29
|
to_a.each(&block)
|
29
30
|
end
|
30
31
|
|
31
|
-
# Iterates over the set of enum instances
|
32
|
-
# @yield [self, Integer] Each instance of this enum, in declaration order,
|
33
|
-
# with its ordinal index
|
34
|
-
# @return [Array<self>] All instances of this enum, in declaration order
|
35
|
-
def each_with_index(&block)
|
36
|
-
to_a.each_with_index(&block)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Iterates over the set of enum instances
|
40
|
-
# @yield [self] Each instance of this enum, in declaration order
|
41
|
-
# @return [Array] An array containing the result of applying `&block`
|
42
|
-
# to each instance of this enum, in instance declaration order
|
43
|
-
def map(&block)
|
44
|
-
to_a.map(&block)
|
45
|
-
end
|
46
|
-
|
47
32
|
# Looks up an enum instance based on its key
|
48
33
|
# @param key [Symbol] the key to look up
|
49
34
|
# @return [self, nil] the corresponding enum instance, or nil
|
@@ -71,6 +56,7 @@ module TypesafeEnum
|
|
71
56
|
# @return [self, nil] the corresponding enum instance, or nil
|
72
57
|
def find_by_ord(ord)
|
73
58
|
return nil if ord > size || ord.negative?
|
59
|
+
|
74
60
|
as_array[ord]
|
75
61
|
end
|
76
62
|
|
@@ -93,21 +79,37 @@ module TypesafeEnum
|
|
93
79
|
end
|
94
80
|
|
95
81
|
def valid_key_and_value(instance)
|
82
|
+
return unless (key = valid_key(instance))
|
83
|
+
|
84
|
+
[key, valid_value(instance)]
|
85
|
+
end
|
86
|
+
|
87
|
+
def valid_key(instance)
|
96
88
|
key = instance.key
|
89
|
+
return key unless (found = find_by_key(key))
|
90
|
+
|
97
91
|
value = instance.value
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
92
|
+
raise NameError, "#{name}::#{key} already exists with value #{found.value.inspect}" unless value == found.value
|
93
|
+
|
94
|
+
warn("ignoring redeclaration of #{name}::#{key} with value #{value.inspect} (source: #{caller(6..6).first})")
|
95
|
+
end
|
96
|
+
|
97
|
+
def valid_value(instance)
|
98
|
+
value = instance.value
|
99
|
+
return value unless (found = find_by_value(value))
|
100
|
+
|
101
|
+
key = instance.key
|
102
|
+
raise NameError, "A #{name} instance with value #{value.inspect} already exists: #{found.key}" unless key == found.key
|
103
|
+
|
104
|
+
# valid_key() should already have warned us, and valid_key_and_value() should have exited early, but just in case
|
105
|
+
# :nocov:
|
106
|
+
warn("ignoring redeclaration of #{name}::#{key} with value #{value.inspect} (source: #{caller(6..6).first})")
|
107
|
+
# :nocov:
|
106
108
|
end
|
107
109
|
|
108
110
|
def register(instance)
|
109
111
|
key, value = valid_key_and_value(instance)
|
110
|
-
return unless key
|
112
|
+
return unless key
|
111
113
|
|
112
114
|
const_set(key.to_s, instance)
|
113
115
|
by_key[key] = instance
|
@@ -150,15 +152,19 @@ module TypesafeEnum
|
|
150
152
|
end
|
151
153
|
|
152
154
|
def to_s
|
153
|
-
"#{self.class}::#{key} [#{ord}] -> #{value}"
|
155
|
+
"#{self.class}::#{key} [#{ord}] -> #{value.inspect}"
|
154
156
|
end
|
155
157
|
|
156
158
|
private
|
157
159
|
|
158
|
-
|
160
|
+
IMPLICIT = Class.new.new
|
161
|
+
private_constant :IMPLICIT
|
162
|
+
|
163
|
+
def initialize(key, value = IMPLICIT, &block)
|
159
164
|
raise TypeError, "#{key} is not a symbol" unless key.is_a?(Symbol)
|
165
|
+
|
160
166
|
@key = key
|
161
|
-
@value = value
|
167
|
+
@value = value == IMPLICIT ? key.to_s.downcase : value
|
162
168
|
@ord = self.class.size
|
163
169
|
self.class.class_exec(self) do |instance|
|
164
170
|
register(instance)
|
@@ -5,8 +5,8 @@ module TypesafeEnum
|
|
5
5
|
NAME = 'typesafe_enum'
|
6
6
|
|
7
7
|
# The version of this gem
|
8
|
-
VERSION = '0.
|
8
|
+
VERSION = '0.3.0'
|
9
9
|
|
10
10
|
# The copyright notice for this gem
|
11
|
-
COPYRIGHT = 'Copyright (c)
|
11
|
+
COPYRIGHT = 'Copyright (c) 2020 The Regents of the University of California'
|
12
12
|
end
|
data/spec/.rubocop.yml
CHANGED
@@ -1,16 +1,19 @@
|
|
1
1
|
inherit_from: ../.rubocop.yml
|
2
2
|
|
3
|
-
|
3
|
+
Lint/ConstantDefinitionInBlock:
|
4
4
|
Enabled: false
|
5
5
|
|
6
|
-
|
6
|
+
Style/ClassAndModuleChildren:
|
7
7
|
Enabled: false
|
8
8
|
|
9
|
-
Metrics/
|
9
|
+
Metrics/AbcSize:
|
10
10
|
Enabled: false
|
11
11
|
|
12
|
-
|
12
|
+
Metrics/BlockLength:
|
13
13
|
Enabled: false
|
14
14
|
|
15
|
-
|
15
|
+
Metrics/ModuleLength:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
Metrics/MethodLength:
|
16
19
|
Enabled: false
|
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'spec_helper'
|
@@ -30,15 +29,31 @@ class Scale < TypesafeEnum::Base
|
|
30
29
|
new :MEGA, 1_000_000
|
31
30
|
end
|
32
31
|
|
32
|
+
class Scheme < TypesafeEnum::Base
|
33
|
+
new :HTTP, 'http'
|
34
|
+
new :HTTPS, 'https'
|
35
|
+
new :EXAMPLE, 'example'
|
36
|
+
new :UNKNOWN, nil
|
37
|
+
end
|
38
|
+
|
33
39
|
module TypesafeEnum
|
34
40
|
describe Base do
|
35
41
|
|
36
|
-
describe
|
37
|
-
it '
|
42
|
+
describe :new do
|
43
|
+
it 'news a constant enum value' do
|
38
44
|
enum = Suit::CLUBS
|
39
45
|
expect(enum).to be_a(Suit)
|
40
46
|
end
|
41
47
|
|
48
|
+
it 'allows nil values' do
|
49
|
+
expect do
|
50
|
+
class ::NilValues < Base
|
51
|
+
new :NONE, nil
|
52
|
+
end
|
53
|
+
end.not_to raise_error
|
54
|
+
expect(::NilValues.to_a).not_to be_empty
|
55
|
+
end
|
56
|
+
|
42
57
|
it 'insists symbols be symbols' do
|
43
58
|
expect do
|
44
59
|
class ::StringKeys < Base
|
@@ -81,6 +96,18 @@ module TypesafeEnum
|
|
81
96
|
expect(::DuplicateValues.find_by_key(:ALSO_SPADES)).to be_nil
|
82
97
|
end
|
83
98
|
|
99
|
+
it 'disallows duplicate nil values' do
|
100
|
+
expect do
|
101
|
+
class ::DuplicateNilValues < Base
|
102
|
+
new :NONE, nil
|
103
|
+
new :NULL, nil
|
104
|
+
end.to raise_error(NameError)
|
105
|
+
expect(::DuplicateNilValues.to_a).to eq([::DuplicateNilValues::NONE])
|
106
|
+
expect(::DuplicateNilValues::NONE.value).to be_nil
|
107
|
+
expect(::DuplicateNilValues.find_by_key(:NULL)).to be_nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
84
111
|
it 'disallows nil keys' do
|
85
112
|
expect do
|
86
113
|
class ::NilKeys < Base
|
@@ -94,7 +121,8 @@ module TypesafeEnum
|
|
94
121
|
class ::IdenticalInstances < Base
|
95
122
|
new :SPADES, 'spades'
|
96
123
|
end
|
97
|
-
|
124
|
+
expected_msg = /ignoring redeclaration of IdenticalInstances::SPADES with value "spades" \(source: .*base_spec.rb:[0-9]+:in `new'\)/
|
125
|
+
expect(::IdenticalInstances).to receive(:warn).once.with(expected_msg)
|
98
126
|
class ::IdenticalInstances < Base
|
99
127
|
new :SPADES, 'spades'
|
100
128
|
end
|
@@ -113,7 +141,7 @@ module TypesafeEnum
|
|
113
141
|
end
|
114
142
|
end
|
115
143
|
|
116
|
-
describe
|
144
|
+
describe :to_a do
|
117
145
|
it 'returns the values as an array' do
|
118
146
|
expect(Suit.to_a).to eq([Suit::CLUBS, Suit::DIAMONDS, Suit::HEARTS, Suit::SPADES])
|
119
147
|
end
|
@@ -125,13 +153,27 @@ module TypesafeEnum
|
|
125
153
|
end
|
126
154
|
end
|
127
155
|
|
128
|
-
describe
|
156
|
+
describe :size do
|
129
157
|
it 'returns the number of enum instnaces' do
|
130
158
|
expect(Suit.size).to eq(4)
|
131
159
|
end
|
132
160
|
end
|
133
161
|
|
134
|
-
describe
|
162
|
+
describe :count do
|
163
|
+
it 'returns the number of enum instnaces' do
|
164
|
+
expect(Suit.count).to eq(4)
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'counts items' do
|
168
|
+
expect(Suit.count(Suit::SPADES)).to eq(1)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'counts items that match a predicate' do
|
172
|
+
expect(Suit.count { |s| s.value.length == 6 }).to eq(2)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
describe :each do
|
135
177
|
it 'iterates the enum values' do
|
136
178
|
expected = [Suit::CLUBS, Suit::DIAMONDS, Suit::HEARTS, Suit::SPADES]
|
137
179
|
index = 0
|
@@ -142,7 +184,7 @@ module TypesafeEnum
|
|
142
184
|
end
|
143
185
|
end
|
144
186
|
|
145
|
-
describe
|
187
|
+
describe :each_with_index do
|
146
188
|
it 'iterates the enum values with indices' do
|
147
189
|
expected = [Suit::CLUBS, Suit::DIAMONDS, Suit::HEARTS, Suit::SPADES]
|
148
190
|
Suit.each_with_index do |s, index|
|
@@ -151,14 +193,21 @@ module TypesafeEnum
|
|
151
193
|
end
|
152
194
|
end
|
153
195
|
|
154
|
-
describe
|
196
|
+
describe :map do
|
155
197
|
it 'maps enum values' do
|
156
198
|
all_keys = Suit.map(&:key)
|
157
199
|
expect(all_keys).to eq(%i[CLUBS DIAMONDS HEARTS SPADES])
|
158
200
|
end
|
159
201
|
end
|
160
202
|
|
161
|
-
describe
|
203
|
+
describe :flat_map do
|
204
|
+
it 'flatmaps enum values' do
|
205
|
+
result = Tarot.flat_map { |t| [t.key, t.value] }
|
206
|
+
expect(result).to eq([:CUPS, 'Cups', :COINS, 'Coins', :WANDS, 'Wands', :SWORDS, 'Swords'])
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe :<=> do
|
162
211
|
it 'orders enum instances' do
|
163
212
|
Suit.each_with_index do |s1, i1|
|
164
213
|
Suit.each_with_index do |s2, i2|
|
@@ -168,7 +217,7 @@ module TypesafeEnum
|
|
168
217
|
end
|
169
218
|
end
|
170
219
|
|
171
|
-
describe
|
220
|
+
describe :== do
|
172
221
|
it 'returns true for identical instances, false otherwise' do
|
173
222
|
Suit.each do |s1|
|
174
223
|
Suit.each do |s2|
|
@@ -190,6 +239,7 @@ module TypesafeEnum
|
|
190
239
|
end
|
191
240
|
end
|
192
241
|
|
242
|
+
# rubocop:disable Security/MarshalLoad
|
193
243
|
it 'survives marshalling' do
|
194
244
|
Suit.each do |s1|
|
195
245
|
dump = Marshal.dump(s1)
|
@@ -198,9 +248,10 @@ module TypesafeEnum
|
|
198
248
|
expect(s2 == s1).to eq(true)
|
199
249
|
end
|
200
250
|
end
|
251
|
+
# rubocop:enable Security/MarshalLoad
|
201
252
|
end
|
202
253
|
|
203
|
-
describe
|
254
|
+
describe :!= do
|
204
255
|
it 'returns false for identical instances, true otherwise' do
|
205
256
|
Suit.each do |s1|
|
206
257
|
Suit.each do |s2|
|
@@ -222,7 +273,7 @@ module TypesafeEnum
|
|
222
273
|
end
|
223
274
|
end
|
224
275
|
|
225
|
-
describe
|
276
|
+
describe :hash do
|
226
277
|
it 'gives consistent values' do
|
227
278
|
Suit.each do |s1|
|
228
279
|
Suit.each do |s2|
|
@@ -245,6 +296,7 @@ module TypesafeEnum
|
|
245
296
|
end
|
246
297
|
end
|
247
298
|
|
299
|
+
# rubocop:disable Security/MarshalLoad
|
248
300
|
it 'survives marshalling' do
|
249
301
|
Suit.each do |s1|
|
250
302
|
dump = Marshal.dump(s1)
|
@@ -252,6 +304,7 @@ module TypesafeEnum
|
|
252
304
|
expect(s2.hash).to eq(s1.hash)
|
253
305
|
end
|
254
306
|
end
|
307
|
+
# rubocop:enable Security/MarshalLoad
|
255
308
|
|
256
309
|
it 'always returns a Fixnum' do
|
257
310
|
Suit.each do |s1|
|
@@ -260,7 +313,7 @@ module TypesafeEnum
|
|
260
313
|
end
|
261
314
|
end
|
262
315
|
|
263
|
-
describe
|
316
|
+
describe :eql? do
|
264
317
|
it 'is consistent with #hash' do
|
265
318
|
Suit.each do |s1|
|
266
319
|
Suit.each do |s2|
|
@@ -270,16 +323,30 @@ module TypesafeEnum
|
|
270
323
|
end
|
271
324
|
end
|
272
325
|
|
273
|
-
describe
|
326
|
+
describe :value do
|
274
327
|
it 'returns the string value of the enum instance' do
|
275
328
|
expected = %w[clubs diamonds hearts spades]
|
276
329
|
Suit.each_with_index do |s, index|
|
277
330
|
expect(s.value).to eq(expected[index])
|
278
331
|
end
|
279
332
|
end
|
333
|
+
|
334
|
+
it 'returns an explicit value' do
|
335
|
+
expected = [10, 100, 1000, 1_000_000]
|
336
|
+
Scale.each_with_index do |s, index|
|
337
|
+
expect(s.value).to eq(expected[index])
|
338
|
+
end
|
339
|
+
end
|
340
|
+
|
341
|
+
it 'supports nil values' do
|
342
|
+
expected = ['http', 'https', 'example', nil]
|
343
|
+
Scheme.each_with_index do |s, index|
|
344
|
+
expect(s.value).to eq(expected[index])
|
345
|
+
end
|
346
|
+
end
|
280
347
|
end
|
281
348
|
|
282
|
-
describe
|
349
|
+
describe :key do
|
283
350
|
it 'returns the symbol key of the enum instance' do
|
284
351
|
expected = %i[CLUBS DIAMONDS HEARTS SPADES]
|
285
352
|
Suit.each_with_index do |s, index|
|
@@ -288,7 +355,7 @@ module TypesafeEnum
|
|
288
355
|
end
|
289
356
|
end
|
290
357
|
|
291
|
-
describe
|
358
|
+
describe :ord do
|
292
359
|
it 'returns the ord value of the enum instance' do
|
293
360
|
Suit.each_with_index do |s, index|
|
294
361
|
expect(s.ord).to eq(index)
|
@@ -296,13 +363,13 @@ module TypesafeEnum
|
|
296
363
|
end
|
297
364
|
end
|
298
365
|
|
299
|
-
describe
|
366
|
+
describe :to_s do
|
300
367
|
it 'provides an informative string' do
|
301
368
|
aggregate_failures 'informative string' do
|
302
|
-
[Suit, Tarot, RGBColor, Scale].each do |ec|
|
369
|
+
[Suit, Tarot, RGBColor, Scale, Scheme].each do |ec|
|
303
370
|
ec.each do |ev|
|
304
371
|
result = ev.to_s
|
305
|
-
[ec.to_s, ev.key, ev.ord, ev.value].each do |info|
|
372
|
+
[ec.to_s, ev.key, ev.ord, ev.value.inspect].each do |info|
|
306
373
|
expect(result).to include(info.to_s)
|
307
374
|
end
|
308
375
|
end
|
@@ -311,7 +378,7 @@ module TypesafeEnum
|
|
311
378
|
end
|
312
379
|
end
|
313
380
|
|
314
|
-
describe
|
381
|
+
describe :find_by_key do
|
315
382
|
it 'maps symbol keys to enum instances' do
|
316
383
|
keys = %i[CLUBS DIAMONDS HEARTS SPADES]
|
317
384
|
expected = Suit.to_a
|
@@ -325,7 +392,7 @@ module TypesafeEnum
|
|
325
392
|
end
|
326
393
|
end
|
327
394
|
|
328
|
-
describe
|
395
|
+
describe :find_by_value do
|
329
396
|
it 'maps values to enum instances' do
|
330
397
|
values = %w[clubs diamonds hearts spades]
|
331
398
|
expected = Suit.to_a
|
@@ -349,9 +416,15 @@ module TypesafeEnum
|
|
349
416
|
expect(Scale.find_by_value(s.value)).to be(s)
|
350
417
|
end
|
351
418
|
end
|
419
|
+
|
420
|
+
it 'supports enums with explicit nil values' do
|
421
|
+
Scheme.each do |s|
|
422
|
+
expect(Scheme.find_by_value(s.value)).to be(s)
|
423
|
+
end
|
424
|
+
end
|
352
425
|
end
|
353
426
|
|
354
|
-
describe
|
427
|
+
describe :find_by_value_str do
|
355
428
|
it 'maps string values to enum instances' do
|
356
429
|
values = %w[clubs diamonds hearts spades]
|
357
430
|
expected = Suit.to_a
|
@@ -375,9 +448,15 @@ module TypesafeEnum
|
|
375
448
|
expect(Scale.find_by_value_str(s.value.to_s)).to be(s)
|
376
449
|
end
|
377
450
|
end
|
451
|
+
|
452
|
+
it 'supports enums with explicit nil values' do
|
453
|
+
Scheme.each do |s|
|
454
|
+
expect(Scheme.find_by_value(s.value)).to be(s)
|
455
|
+
end
|
456
|
+
end
|
378
457
|
end
|
379
458
|
|
380
|
-
describe
|
459
|
+
describe :find_by_ord do
|
381
460
|
it 'maps ordinal indices to enum instances' do
|
382
461
|
Suit.each do |s|
|
383
462
|
expect(Suit.find_by_ord(s.ord)).to be(s)
|
@@ -432,5 +511,9 @@ module TypesafeEnum
|
|
432
511
|
|
433
512
|
expect(Operation.map { |op| op.eval(39, 23) }).to eq([39 + 23, 39 - 23])
|
434
513
|
end
|
514
|
+
|
515
|
+
it 'is an Enumerable' do
|
516
|
+
expect(Suit).to be_an(Enumerable)
|
517
|
+
end
|
435
518
|
end
|
436
519
|
end
|