typesafe_enum 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6dca44bfdc19636b439aea18d0a5bbb195150fcf
4
- data.tar.gz: ae8b31bcd16f05536e1bb2ffd9346fbd395465e7
3
+ metadata.gz: 5b0677a4297fd6de2704786aa65b16b10a3a89de
4
+ data.tar.gz: ae7122293d92ba5417e684ae9746fa798f9d6f47
5
5
  SHA512:
6
- metadata.gz: d8c40232f8fa100c7de8f49d830e20bce082126d951a69a4e53294a89134647c6cf2d0244034efe47bb88348a70352d4b3c061c5ff6c6a0d19f296e4a4de154d
7
- data.tar.gz: 24543c5f5b1b72dbf554662275d47c918ef3807e723648aebe34552b217b52e82a91f9a20f35d9a7569ace4279dcdebefb00df0b136099a2f802fb66ac6c9812
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
@@ -59,51 +59,40 @@ module TypesafeEnum
59
59
 
60
60
  private
61
61
 
62
- attr_accessor :by_key
63
- attr_accessor :by_value
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 register(instance)
77
- ensure_registries
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 ensure_registries
87
- self.by_key ||= {}
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
- begin
97
- fail NameError, "#{name}::#{key} already exists" if find_by_key(key)
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
- rescue NameError => e
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
@@ -3,7 +3,7 @@ module TypesafeEnum
3
3
  NAME = 'typesafe_enum'
4
4
 
5
5
  # The version of this gem
6
- VERSION = '0.1.3'
6
+ VERSION = '0.1.4'
7
7
 
8
8
  # The copyright notice for this gem
9
9
  COPYRIGHT = 'Copyright (c) 2015 The Regents of the University of California'
@@ -1,27 +1,27 @@
1
1
  # coding: UTF-8
2
2
  require 'spec_helper'
3
3
 
4
- class ::Suit < TypesafeEnum::Base
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 ::Tarot < TypesafeEnum::Base
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 ::RGBColor < TypesafeEnum::Base
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 ::Scale < TypesafeEnum::Base
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 ::Cheat < Base
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 ::Cheat < Base
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 ::Cheat < Base
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 { ::Cheat.class }.to raise_error(NameError)
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 ::Cheat < Base
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
- expect { ::Cheat.class }.to raise_error(NameError)
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.3
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-17 00:00:00.000000000 Z
11
+ date: 2015-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler