typesafe_enum 0.1.3 → 0.1.4
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 +4 -4
- data/CHANGES.md +8 -0
- data/README.md +70 -0
- data/lib/typesafe_enum/base.rb +21 -32
- data/lib/typesafe_enum/module_info.rb +1 -1
- data/spec/unit/typesafe_enum/base_spec.rb +37 -13
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b0677a4297fd6de2704786aa65b16b10a3a89de
|
|
4
|
+
data.tar.gz: ae7122293d92ba5417e684ae9746fa798f9d6f47
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 44ec4665cb20ee046932e909d91738273c1591c06f9dd103693a2f38fb9082b160c0ab1e4941e6dc5901a5a3a70bcb4b7205f5a732d9f17d166b47e00e254d48
|
|
7
|
+
data.tar.gz: 069df54602db3f496024d3d99d1a8d400f204ba4bbf4d6f1cc8e1d3e0b717ae6036279208a8e3eeb577b49eb1f9a5b85ee0e6978e8cb5e826fcbcf8576196574
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
## 0.1.4
|
|
2
|
+
|
|
3
|
+
- Exact duplicate instances (e.g. due to multiple `requires`) are now ignored with a warning,
|
|
4
|
+
instead of causing a `NameError`. Duplicate keys with different values, and duplicate values
|
|
5
|
+
with different keys, still raise a `NameError`.
|
|
6
|
+
- `NameErrors` due to invalid keys or values no longer cause the enum class to be undefined.
|
|
7
|
+
However, the invalid instances will still not be registered and no constants created for them.
|
|
8
|
+
|
|
1
9
|
## 0.1.3
|
|
2
10
|
|
|
3
11
|
- Fixed issue where invalid classes weren't properly removed after duplicate name declarations,
|
data/README.md
CHANGED
|
@@ -69,6 +69,76 @@ Scale::KILO.value
|
|
|
69
69
|
# => 1000
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
Declaring two instances with the same key will produce an error:
|
|
73
|
+
|
|
74
|
+
```ruby
|
|
75
|
+
class Suit < TypesafeEnum::Base
|
|
76
|
+
new :CLUBS
|
|
77
|
+
new :DIAMONDS
|
|
78
|
+
new :HEARTS
|
|
79
|
+
new :SPADES
|
|
80
|
+
new :SPADES, '♠'
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
typesafe_enum/lib/typesafe_enum/base.rb:88:in `valid_key_and_value': Suit::SPADES already exists (NameError)
|
|
86
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:98:in `register'
|
|
87
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:138:in `block in initialize'
|
|
88
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:137:in `class_exec'
|
|
89
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:137:in `initialize'
|
|
90
|
+
from ./scratch.rb:11:in `new'
|
|
91
|
+
from ./scratch.rb:11:in `<class:Suit>'
|
|
92
|
+
from ./scratch.rb:6:in `<main>'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Likewise two instances with the same value but different keys:
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
class Tarot < TypesafeEnum::Base
|
|
99
|
+
new :CUPS, 'Cups'
|
|
100
|
+
new :COINS, 'Coins'
|
|
101
|
+
new :WANDS, 'Wands'
|
|
102
|
+
new :SWORDS, 'Swords'
|
|
103
|
+
new :STAVES, 'Wands'
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
/typesafe_enum/lib/typesafe_enum/base.rb:92:in `valid_key_and_value': A Tarot instance with value 'Wands' already exists (NameError)
|
|
109
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:98:in `register'
|
|
110
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:138:in `block in initialize'
|
|
111
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:137:in `class_exec'
|
|
112
|
+
from /Users/dmoles/Work/Stash/typesafe_enum/lib/typesafe_enum/base.rb:137:in `initialize'
|
|
113
|
+
from ./scratch.rb:11:in `new'
|
|
114
|
+
from ./scratch.rb:11:in `<class:Tarot>'
|
|
115
|
+
from ./scratch.rb:6:in `<main>'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
However, declaring an identical key/value pair will be ignored with a warning, to avoid unnecessary errors
|
|
119
|
+
when, e.g., a declaration file is accidentally `required` twice.
|
|
120
|
+
|
|
121
|
+
```ruby
|
|
122
|
+
class Tarot < TypesafeEnum::Base
|
|
123
|
+
new :CUPS, 'Cups'
|
|
124
|
+
new :COINS, 'Coins'
|
|
125
|
+
new :WANDS, 'Wands'
|
|
126
|
+
new :SWORDS, 'Swords'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
class Tarot < TypesafeEnum::Base
|
|
130
|
+
new :CUPS, 'Cups'
|
|
131
|
+
new :COINS, 'Coins'
|
|
132
|
+
new :WANDS, 'Wands'
|
|
133
|
+
new :SWORDS, 'Swords'
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# => ignoring redeclaration of Tarot::CUPS with value: Cups
|
|
137
|
+
# => ignoring redeclaration of Tarot::COINS with value: Coins
|
|
138
|
+
# => ignoring redeclaration of Tarot::WANDS with value: Wands
|
|
139
|
+
# => ignoring redeclaration of Tarot::SWORDS with value: Swords
|
|
140
|
+
```
|
|
141
|
+
|
|
72
142
|
## Ordering
|
|
73
143
|
|
|
74
144
|
Enum instances have an ordinal value corresponding to their declaration
|
data/lib/typesafe_enum/base.rb
CHANGED
|
@@ -59,51 +59,40 @@ module TypesafeEnum
|
|
|
59
59
|
|
|
60
60
|
private
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
attr_accessor :as_array
|
|
65
|
-
|
|
66
|
-
def parent
|
|
67
|
-
parent_name = name =~ /::[^:]+\Z/ ? $`.freeze : nil
|
|
68
|
-
parent_name ? Object.const_get(parent_name) : Object
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def undefine_class
|
|
72
|
-
class_value = name.split('::').last || ''
|
|
73
|
-
parent.send(:remove_const, class_value)
|
|
62
|
+
def by_key
|
|
63
|
+
@by_key ||= {}
|
|
74
64
|
end
|
|
75
65
|
|
|
76
|
-
def
|
|
77
|
-
|
|
78
|
-
key, value = valid_key_and_value(instance)
|
|
79
|
-
|
|
80
|
-
by_key[key] = instance
|
|
81
|
-
by_value[value] = instance
|
|
82
|
-
as_array << instance
|
|
83
|
-
const_set(key.to_s, instance)
|
|
66
|
+
def by_value
|
|
67
|
+
@by_value ||= {}
|
|
84
68
|
end
|
|
85
69
|
|
|
86
|
-
def
|
|
87
|
-
|
|
88
|
-
self.by_value ||= {}
|
|
89
|
-
self.as_array ||= []
|
|
70
|
+
def as_array
|
|
71
|
+
@as_array ||= []
|
|
90
72
|
end
|
|
91
73
|
|
|
92
74
|
def valid_key_and_value(instance)
|
|
93
75
|
key = instance.key
|
|
94
76
|
value = instance.value
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
77
|
+
if (found = find_by_key(key))
|
|
78
|
+
fail NameError, "#{name}::#{key} already exists" unless value == found.value
|
|
79
|
+
warn("ignoring redeclaration of #{name}::#{key} with value: #{value}")
|
|
80
|
+
nil
|
|
81
|
+
else
|
|
98
82
|
fail NameError, "A #{name} instance with value '#{value}' already exists" if find_by_value(value)
|
|
99
|
-
|
|
100
|
-
undefine_class
|
|
101
|
-
raise e
|
|
83
|
+
[key, value]
|
|
102
84
|
end
|
|
103
|
-
|
|
104
|
-
[key, value]
|
|
105
85
|
end
|
|
106
86
|
|
|
87
|
+
def register(instance)
|
|
88
|
+
key, value = valid_key_and_value(instance)
|
|
89
|
+
return unless key && value
|
|
90
|
+
|
|
91
|
+
const_set(key.to_s, instance)
|
|
92
|
+
by_key[key] = instance
|
|
93
|
+
by_value[value] = instance
|
|
94
|
+
as_array << instance
|
|
95
|
+
end
|
|
107
96
|
end
|
|
108
97
|
|
|
109
98
|
# The symbol key for the enum instance
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
# coding: UTF-8
|
|
2
2
|
require 'spec_helper'
|
|
3
3
|
|
|
4
|
-
class
|
|
4
|
+
class Suit < TypesafeEnum::Base
|
|
5
5
|
new :CLUBS
|
|
6
6
|
new :DIAMONDS
|
|
7
7
|
new :HEARTS
|
|
8
8
|
new :SPADES
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
class
|
|
11
|
+
class Tarot < TypesafeEnum::Base
|
|
12
12
|
new :CUPS, 'Cups'
|
|
13
13
|
new :COINS, 'Coins'
|
|
14
14
|
new :WANDS, 'Wands'
|
|
15
15
|
new :SWORDS, 'Swords'
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
class
|
|
18
|
+
class RGBColor < TypesafeEnum::Base
|
|
19
19
|
new :RED, :red
|
|
20
20
|
new :GREEN, :green
|
|
21
21
|
new :BLUE, :blue
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
class
|
|
24
|
+
class Scale < TypesafeEnum::Base
|
|
25
25
|
new :DECA, 10
|
|
26
26
|
new :HECTO, 100
|
|
27
27
|
new :KILO, 1_000
|
|
@@ -39,40 +39,64 @@ module TypesafeEnum
|
|
|
39
39
|
|
|
40
40
|
it 'insists symbols be symbols' do
|
|
41
41
|
expect do
|
|
42
|
-
class ::
|
|
42
|
+
class ::StringKeys < Base
|
|
43
43
|
new 'spades', 'spades'
|
|
44
44
|
end
|
|
45
45
|
end.to raise_error(TypeError)
|
|
46
|
+
expect(::StringKeys.to_a).to be_empty
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
it 'insists symbols be uppercase' do
|
|
49
50
|
expect do
|
|
50
|
-
class ::
|
|
51
|
+
class ::LowerCaseKeys < Base
|
|
51
52
|
new :spades, 'spades'
|
|
52
53
|
end
|
|
53
54
|
end.to raise_error(NameError)
|
|
55
|
+
expect(::LowerCaseKeys.to_a).to be_empty
|
|
54
56
|
end
|
|
55
57
|
|
|
56
|
-
it 'disallows duplicate symbols' do
|
|
58
|
+
it 'disallows duplicate symbols with different values' do
|
|
57
59
|
expect do
|
|
58
|
-
class ::
|
|
60
|
+
class ::DuplicateSymbols < Base
|
|
59
61
|
new :SPADES, 'spades'
|
|
60
62
|
new :SPADES, 'more spades'
|
|
61
63
|
end
|
|
62
64
|
end.to raise_error(NameError)
|
|
63
|
-
|
|
64
|
-
expect
|
|
65
|
+
expect(::DuplicateSymbols.to_a).to eq([::DuplicateSymbols::SPADES])
|
|
66
|
+
expect(::DuplicateSymbols::SPADES.value).to eq('spades')
|
|
67
|
+
expect(::DuplicateSymbols.find_by_value('more spades')).to be_nil
|
|
65
68
|
end
|
|
66
69
|
|
|
67
|
-
it 'disallows duplicate values' do
|
|
70
|
+
it 'disallows duplicate values with different symbols' do
|
|
68
71
|
expect do
|
|
69
|
-
class ::
|
|
72
|
+
class ::DuplicateValues < Base
|
|
70
73
|
new :SPADES, 'spades'
|
|
71
74
|
new :ALSO_SPADES, 'spades'
|
|
72
75
|
end
|
|
73
76
|
end.to raise_error(NameError)
|
|
77
|
+
expect(::DuplicateValues.to_a).to eq([::DuplicateValues::SPADES])
|
|
78
|
+
expect(::DuplicateValues::SPADES.value).to eq('spades')
|
|
79
|
+
expect(::DuplicateValues.find_by_key(:ALSO_SPADES)).to be_nil
|
|
80
|
+
end
|
|
74
81
|
|
|
75
|
-
|
|
82
|
+
it 'disallows nil keys' do
|
|
83
|
+
expect do
|
|
84
|
+
class ::NilKeys < Base
|
|
85
|
+
new nil, 'nil'
|
|
86
|
+
end
|
|
87
|
+
end.to raise_error(TypeError)
|
|
88
|
+
expect(::NilKeys.to_a).to be_empty
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'allows, but ignores redeclaration of identical instances' do
|
|
92
|
+
class ::IdenticalInstances < Base
|
|
93
|
+
new :SPADES, 'spades'
|
|
94
|
+
end
|
|
95
|
+
expect(::IdenticalInstances).to receive(:warn).with('ignoring redeclaration of IdenticalInstances::SPADES with value: spades')
|
|
96
|
+
class ::IdenticalInstances < Base
|
|
97
|
+
new :SPADES, 'spades'
|
|
98
|
+
end
|
|
99
|
+
expect(::IdenticalInstances.to_a).to eq([::IdenticalInstances::SPADES])
|
|
76
100
|
end
|
|
77
101
|
|
|
78
102
|
it 'defaults the value to a lower-cased version of the symbol' do
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: typesafe_enum
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Moles
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-12-
|
|
11
|
+
date: 2015-12-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|