ruby-enum 1.0.0 → 1.2.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/Dangerfile +2 -0
  4. data/Gemfile +6 -5
  5. data/Gemfile.lock +128 -93
  6. data/README.md +37 -4
  7. data/RELEASING.md +14 -5
  8. data/Rakefile +10 -0
  9. data/UPGRADING.md +39 -0
  10. data/benchmarks/basic.rb +61 -0
  11. data/benchmarks/inheritance.rb +53 -0
  12. data/lib/ruby-enum/enum.rb +65 -25
  13. data/lib/ruby-enum/errors/base.rb +2 -2
  14. data/lib/ruby-enum/version.rb +1 -1
  15. data/pkg/ruby-enum-0.8.0.gem +0 -0
  16. data/pkg/ruby-enum-0.9.0.gem +0 -0
  17. data/pkg/ruby-enum-1.1.0.gem +0 -0
  18. data/spec/ruby-enum/enum/case_spec.rb +35 -34
  19. data/spec/ruby-enum/enum_spec.rb +212 -39
  20. data/spec/spec_helper.rb +2 -2
  21. data/spec_i18n/Gemfile.lock +26 -16
  22. data/spec_i18n/spec/i18n_spec.rb +9 -7
  23. metadata +8 -33
  24. data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc.png +0 -0
  25. data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
  26. data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_both.png +0 -0
  27. data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc.png +0 -0
  28. data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
  29. data/coverage/assets/0.12.3/application.css +0 -1
  30. data/coverage/assets/0.12.3/application.js +0 -7
  31. data/coverage/assets/0.12.3/colorbox/border.png +0 -0
  32. data/coverage/assets/0.12.3/colorbox/controls.png +0 -0
  33. data/coverage/assets/0.12.3/colorbox/loading.gif +0 -0
  34. data/coverage/assets/0.12.3/colorbox/loading_background.png +0 -0
  35. data/coverage/assets/0.12.3/favicon_green.png +0 -0
  36. data/coverage/assets/0.12.3/favicon_red.png +0 -0
  37. data/coverage/assets/0.12.3/favicon_yellow.png +0 -0
  38. data/coverage/assets/0.12.3/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  39. data/coverage/assets/0.12.3/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  40. data/coverage/assets/0.12.3/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  41. data/coverage/assets/0.12.3/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  42. data/coverage/assets/0.12.3/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  43. data/coverage/assets/0.12.3/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  44. data/coverage/assets/0.12.3/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  45. data/coverage/assets/0.12.3/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  46. data/coverage/assets/0.12.3/images/ui-icons_222222_256x240.png +0 -0
  47. data/coverage/assets/0.12.3/images/ui-icons_2e83ff_256x240.png +0 -0
  48. data/coverage/assets/0.12.3/images/ui-icons_454545_256x240.png +0 -0
  49. data/coverage/assets/0.12.3/images/ui-icons_888888_256x240.png +0 -0
  50. data/coverage/assets/0.12.3/images/ui-icons_cd0a0a_256x240.png +0 -0
  51. data/coverage/assets/0.12.3/loading.gif +0 -0
  52. data/coverage/assets/0.12.3/magnify.png +0 -0
  53. data/coverage/index.html +0 -8785
@@ -19,6 +19,9 @@ module Ruby
19
19
  base.extend ClassMethods
20
20
 
21
21
  base.private_class_method(:new)
22
+
23
+ base.instance_variable_set(:@_own_enum_hash, {})
24
+ base.instance_variable_set(:@_own_enums_by_value, {})
22
25
  end
23
26
 
24
27
  module ClassMethods
@@ -28,9 +31,6 @@ module Ruby
28
31
  # [key] Enumerator key.
29
32
  # [value] Enumerator value.
30
33
  def define(key, value = key)
31
- @_enum_hash ||= {}
32
- @_enums_by_value ||= {}
33
-
34
34
  validate_key!(key)
35
35
  validate_value!(value)
36
36
 
@@ -45,18 +45,21 @@ module Ruby
45
45
 
46
46
  def store_new_instance(key, value)
47
47
  new_instance = new(key, value)
48
- @_enum_hash[key] = new_instance
49
- @_enums_by_value[value] = new_instance
48
+ _own_enum_hash[key] = new_instance
49
+ _own_enums_by_value[value] = new_instance
50
+
51
+ # Invalidate memoized, merged hashes since this class' own enums changed.
52
+ @_enum_hash = @_enums_by_value = nil
50
53
  end
51
54
 
52
55
  def const_missing(key)
53
56
  raise Ruby::Enum::Errors::UninitializedConstantError, name: name, key: key
54
57
  end
55
58
 
56
- # Iterate over all enumerated values.
59
+ # Iterate over all enumerated values, including those defined in a superclass.
57
60
  # Required for Enumerable mixin
58
61
  def each(&block)
59
- @_enum_hash.each(&block)
62
+ _enum_hash.each(&block)
60
63
  end
61
64
 
62
65
  # Attempt to parse an enum key and return the
@@ -74,56 +77,56 @@ module Ruby
74
77
  nil
75
78
  end
76
79
 
77
- # Whether the specified key exists in this enum.
80
+ # Whether the specified key exists in this enum, including those defined in a superclass.
78
81
  #
79
82
  # === Parameters
80
83
  # [k] The string key to check.
81
84
  #
82
85
  # Returns true if the key exists, false otherwise.
83
86
  def key?(k)
84
- @_enum_hash.key?(k)
87
+ _enum_hash.key?(k)
85
88
  end
86
89
 
87
- # Gets the string value for the specified key.
90
+ # Gets the string value for the specified key, including those defined in a superclass.
88
91
  #
89
92
  # === Parameters
90
93
  # [k] The key symbol to get the value for.
91
94
  #
92
95
  # Returns the corresponding enum instance or nil.
93
96
  def value(k)
94
- enum = @_enum_hash[k]
97
+ enum = _enum_hash[k]
95
98
  enum&.value
96
99
  end
97
100
 
98
- # Whether the specified value exists in this enum.
101
+ # Whether the specified value exists in this enum, including those defined in a superclass.
99
102
  #
100
103
  # === Parameters
101
104
  # [k] The string value to check.
102
105
  #
103
106
  # Returns true if the value exists, false otherwise.
104
107
  def value?(v)
105
- @_enums_by_value.key?(v)
108
+ _enums_by_value.key?(v)
106
109
  end
107
110
 
108
- # Gets the key symbol for the specified value.
111
+ # Gets the key symbol for the specified value, including those defined in a superclass.
109
112
  #
110
113
  # === Parameters
111
114
  # [v] The string value to parse.
112
115
  #
113
116
  # Returns the corresponding key symbol or nil.
114
117
  def key(v)
115
- enum = @_enums_by_value[v]
118
+ enum = _enums_by_value[v]
116
119
  enum&.key
117
120
  end
118
121
 
119
- # Returns all enum keys.
122
+ # Returns all enum keys, including those defined in a superclass.
120
123
  def keys
121
- @_enum_hash.values.map(&:key)
124
+ _enum_hash.values.map(&:key)
122
125
  end
123
126
 
124
127
  # Returns all enum values.
125
128
  def values
126
- result = @_enum_hash.values.map(&:value)
129
+ result = _own_enum_hash.values.map(&:value)
127
130
 
128
131
  if superclass < Ruby::Enum
129
132
  superclass.values + result
@@ -132,40 +135,77 @@ module Ruby
132
135
  end
133
136
  end
134
137
 
135
- # Iterate over all enumerated values.
138
+ # Iterate over all enumerated values, including those defined in a superclass.
136
139
  # Required for Enumerable mixin
137
140
  def each_value(&_block)
138
- @_enum_hash.each_value do |v|
141
+ _enum_hash.each_value do |v|
139
142
  yield v.value
140
143
  end
141
144
  end
142
145
 
143
- # Iterate over all enumerated keys.
146
+ # Iterate over all enumerated keys, including those defined in a superclass.
144
147
  # Required for Enumerable mixin
145
148
  def each_key(&_block)
146
- @_enum_hash.each_value do |v|
149
+ _enum_hash.each_value do |v|
147
150
  yield v.key
148
151
  end
149
152
  end
150
153
 
154
+ # Returns a hash of key:values, including those defined in a superclass.
151
155
  def to_h
152
- @_enum_hash.transform_values(&:value)
156
+ _enum_hash.transform_values(&:value)
153
157
  end
154
158
 
155
159
  private
156
160
 
161
+ # Returns this class' own enum hash, defaulting to an empty hash.
162
+ #
163
+ # A subclass that does not `define` any of its own enums does not have
164
+ # its `@_own_enum_hash` instance variable set, since it's only initialized
165
+ # in `define` and in the `included` hook.
166
+ def _own_enum_hash
167
+ @_own_enum_hash ||= {}
168
+ end
169
+
170
+ # Returns this class' own enums-by-value hash, defaulting to an empty hash.
171
+ def _own_enums_by_value
172
+ @_own_enums_by_value ||= {}
173
+ end
174
+
175
+ # Returns the enum hash for this class merged with all of its superclasses,
176
+ # with keys defined in this class taking precedence over those inherited
177
+ # from a superclass.
178
+ def _enum_hash
179
+ @_enum_hash ||= if superclass < Ruby::Enum
180
+ superclass.send(:_enum_hash).merge(_own_enum_hash)
181
+ else
182
+ _own_enum_hash
183
+ end
184
+ end
185
+
186
+ # Returns the enums-by-value hash for this class merged with all of its
187
+ # superclasses, with values defined in this class taking precedence over
188
+ # those inherited from a superclass.
189
+ def _enums_by_value
190
+ @_enums_by_value ||= if superclass < Ruby::Enum
191
+ superclass.send(:_enums_by_value).merge(_own_enums_by_value)
192
+ else
193
+ _own_enums_by_value
194
+ end
195
+ end
196
+
157
197
  def upper?(s)
158
198
  !/[[:upper:]]/.match(s).nil?
159
199
  end
160
200
 
161
201
  def validate_key!(key)
162
- return unless @_enum_hash.key?(key)
202
+ return unless _own_enum_hash.key?(key)
163
203
 
164
204
  raise Ruby::Enum::Errors::DuplicateKeyError, name: name, key: key
165
205
  end
166
206
 
167
207
  def validate_value!(value)
168
- return unless @_enums_by_value.key?(value)
208
+ return unless _own_enums_by_value.key?(value)
169
209
 
170
210
  raise Ruby::Enum::Errors::DuplicateValueError, name: name, value: value
171
211
  end
@@ -26,10 +26,10 @@ module Ruby
26
26
  "\nSummary:\n #{@summary}" + "\nResolution:\n #{@resolution}"
27
27
  end
28
28
 
29
- private
30
-
31
29
  BASE_KEY = 'ruby.enum.errors.messages' # :nodoc:
32
30
 
31
+ private
32
+
33
33
  # Given the key of the specific error and the options hash, translate the
34
34
  # message.
35
35
  #
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ruby
4
4
  module Enum
5
- VERSION = '1.0.0'
5
+ VERSION = '1.2.0'
6
6
  end
7
7
  end
Binary file
Binary file
Binary file
@@ -2,55 +2,56 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- RSpec.describe Ruby::Enum::Case do
6
- test_enum =
7
- Class.new do
8
- include Ruby::Enum
9
- include Ruby::Enum::Case
10
-
11
- define :RED, :red
12
- define :GREEN, :green
13
- define :BLUE, :blue
14
- end
5
+ module Case
6
+ class Colors
7
+ include Ruby::Enum
8
+ include Ruby::Enum::Case
9
+
10
+ define :RED, :red
11
+ define :GREEN, :green
12
+ define :BLUE, :blue
13
+ end
14
+ end
15
15
 
16
+ RSpec.describe Ruby::Enum::Case do
16
17
  describe '.case' do
17
18
  context 'when all cases are defined' do
18
- subject { test_enum.case(test_enum::RED, cases) }
19
+ subject { Case::Colors.case(Case::Colors::RED, cases) }
19
20
 
20
21
  let(:cases) do
21
22
  {
22
- [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
23
- test_enum::BLUE => -> { 'blue' }
23
+ [Case::Colors::RED, Case::Colors::GREEN] => -> { 'red or green' },
24
+ Case::Colors::BLUE => -> { 'blue' }
24
25
  }
25
26
  end
26
27
 
27
28
  it { is_expected.to eq('red or green') }
28
29
 
29
30
  context 'when the value is nil' do
30
- subject { test_enum.case(nil, cases) }
31
+ subject { Case::Colors.case(nil, cases) }
31
32
 
32
33
  it { is_expected.to be_nil }
33
34
  end
34
35
 
35
36
  context 'when the value is empty' do
36
- subject { test_enum.case('', cases) }
37
+ subject { Case::Colors.case('', cases) }
37
38
 
38
39
  it { is_expected.to be_nil }
39
40
  end
40
41
 
41
42
  context 'when the value is the value of the enum' do
42
- subject { test_enum.case(:red, cases) }
43
+ subject { Case::Colors.case(:red, cases) }
43
44
 
44
45
  it { is_expected.to eq('red or green') }
45
46
  end
46
47
 
47
48
  context 'when the value is used inside the lambda' do
48
- subject { test_enum.case(test_enum::RED, cases) }
49
+ subject { Case::Colors.case(Case::Colors::RED, cases) }
49
50
 
50
51
  let(:cases) do
51
52
  {
52
- [test_enum::RED, test_enum::GREEN] => ->(color) { "is #{color}" },
53
- test_enum::BLUE => -> { 'blue' }
53
+ [Case::Colors::RED, Case::Colors::GREEN] => ->(color) { "is #{color}" },
54
+ Case::Colors::BLUE => -> { 'blue' }
54
55
  }
55
56
  end
56
57
 
@@ -60,12 +61,12 @@ RSpec.describe Ruby::Enum::Case do
60
61
 
61
62
  context 'when there are mutliple matches' do
62
63
  subject do
63
- test_enum.case(
64
- test_enum::RED,
64
+ Case::Colors.case(
65
+ Case::Colors::RED,
65
66
  {
66
- [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
67
- test_enum::RED => -> { 'red' },
68
- test_enum::BLUE => -> { 'blue' }
67
+ [Case::Colors::RED, Case::Colors::GREEN] => -> { 'red or green' },
68
+ Case::Colors::RED => -> { 'red' },
69
+ Case::Colors::BLUE => -> { 'blue' }
69
70
  }
70
71
  )
71
72
  end
@@ -76,9 +77,9 @@ RSpec.describe Ruby::Enum::Case do
76
77
  context 'when not all cases are defined' do
77
78
  it 'raises an error' do
78
79
  expect do
79
- test_enum.case(
80
- test_enum::RED,
81
- { [test_enum::RED, test_enum::GREEN] => -> { 'red or green' } }
80
+ Case::Colors.case(
81
+ Case::Colors::RED,
82
+ { [Case::Colors::RED, Case::Colors::GREEN] => -> { 'red or green' } }
82
83
  )
83
84
  end.to raise_error(Ruby::Enum::Case::ClassMethods::NotAllCasesHandledError)
84
85
  end
@@ -87,10 +88,10 @@ RSpec.describe Ruby::Enum::Case do
87
88
  context 'when not all cases are defined but :else is specified (default case)' do
88
89
  it 'does not raise an error' do
89
90
  expect do
90
- result = test_enum.case(
91
- test_enum::BLUE,
91
+ result = Case::Colors.case(
92
+ Case::Colors::BLUE,
92
93
  {
93
- [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
94
+ [Case::Colors::RED, Case::Colors::GREEN] => -> { 'red or green' },
94
95
  else: -> { 'blue' }
95
96
  }
96
97
  )
@@ -103,11 +104,11 @@ RSpec.describe Ruby::Enum::Case do
103
104
  context 'when a superfluous case is defined' do
104
105
  it 'raises an error' do
105
106
  expect do
106
- test_enum.case(
107
- test_enum::RED,
107
+ Case::Colors.case(
108
+ Case::Colors::RED,
108
109
  {
109
- [test_enum::RED, test_enum::GREEN] => -> { 'red or green' },
110
- test_enum::BLUE => -> { 'blue' },
110
+ [Case::Colors::RED, Case::Colors::GREEN] => -> { 'red or green' },
111
+ Case::Colors::BLUE => -> { 'blue' },
111
112
  :something => -> { 'green' }
112
113
  }
113
114
  )