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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/Dangerfile +2 -0
- data/Gemfile +6 -5
- data/Gemfile.lock +128 -93
- data/README.md +37 -4
- data/RELEASING.md +14 -5
- data/Rakefile +10 -0
- data/UPGRADING.md +39 -0
- data/benchmarks/basic.rb +61 -0
- data/benchmarks/inheritance.rb +53 -0
- data/lib/ruby-enum/enum.rb +65 -25
- data/lib/ruby-enum/errors/base.rb +2 -2
- data/lib/ruby-enum/version.rb +1 -1
- data/pkg/ruby-enum-0.8.0.gem +0 -0
- data/pkg/ruby-enum-0.9.0.gem +0 -0
- data/pkg/ruby-enum-1.1.0.gem +0 -0
- data/spec/ruby-enum/enum/case_spec.rb +35 -34
- data/spec/ruby-enum/enum_spec.rb +212 -39
- data/spec/spec_helper.rb +2 -2
- data/spec_i18n/Gemfile.lock +26 -16
- data/spec_i18n/spec/i18n_spec.rb +9 -7
- metadata +8 -33
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_asc_disabled.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_both.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc.png +0 -0
- data/coverage/assets/0.12.3/DataTables-1.10.20/images/sort_desc_disabled.png +0 -0
- data/coverage/assets/0.12.3/application.css +0 -1
- data/coverage/assets/0.12.3/application.js +0 -7
- data/coverage/assets/0.12.3/colorbox/border.png +0 -0
- data/coverage/assets/0.12.3/colorbox/controls.png +0 -0
- data/coverage/assets/0.12.3/colorbox/loading.gif +0 -0
- data/coverage/assets/0.12.3/colorbox/loading_background.png +0 -0
- data/coverage/assets/0.12.3/favicon_green.png +0 -0
- data/coverage/assets/0.12.3/favicon_red.png +0 -0
- data/coverage/assets/0.12.3/favicon_yellow.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/coverage/assets/0.12.3/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_222222_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_2e83ff_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_454545_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_888888_256x240.png +0 -0
- data/coverage/assets/0.12.3/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/coverage/assets/0.12.3/loading.gif +0 -0
- data/coverage/assets/0.12.3/magnify.png +0 -0
- data/coverage/index.html +0 -8785
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0424fcb26d8fc260165a669fa7be1d83e41a3a8e967ad606c5eb72abb656b349
|
|
4
|
+
data.tar.gz: 2ea8e9dc094a9612447679c7d5bebf88ac466b1c1b9a5f666d3ce5a8d0981965
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 024aac1db4f01d3528a1130817e3db22e7e413d598e99d5dc333a040057896129420193731cec1706922a5c462322809e4e6ce5de2d871f1d2492e67990b56ab
|
|
7
|
+
data.tar.gz: c8a5b49346df275afd18502410a9e24a5806fdfdb0d31d2a7a53783edf8b592b3fe27789ca19d26f32d3937142f40c561b2a9d87ef5cff66e9aa7d05c3054cf6
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
### 1.2.0 (2026/8/14)
|
|
2
|
+
|
|
3
|
+
* [#49](https://github.com/dblock/ruby-enum/issues/49): Fixed `NoMethodError` on `keys`, `values`, `key?`, `value?`, `key`, `value`, `to_h`, `parse` and `each` when a subclass defines no enums of its own - [@dblock](https://github.com/dblock).
|
|
4
|
+
* [#49](https://github.com/dblock/ruby-enum/issues/49): `keys`, `key?`, `value?`, `key`, `value`, `to_h`, `parse` and `each` now include enums defined in a superclass, matching the existing behavior of `values` - [@dblock](https://github.com/dblock).
|
|
5
|
+
* [#61](https://github.com/dblock/ruby-enum/pull/61): Document performance overhead in README, add `rake benchmark:basic` - [@dblock](https://github.com/dblock).
|
|
6
|
+
|
|
7
|
+
### 1.1.0 (2026/6/20)
|
|
8
|
+
|
|
9
|
+
* [#56](https://github.com/dblock/ruby-enum/pull/56): Fix `DuplicateKeyError` when the enum class is reloaded - [@flvrone](https://github.com/flvrone).
|
|
10
|
+
* [#54](https://github.com/dblock/ruby-enum/pull/54): Add support for Ruby 4.0 - [@dblock](https://github.com/dblock).
|
|
11
|
+
* [#53](https://github.com/dblock/ruby-enum/pull/53): Replace code climate with coveralls - [@dblock](https://github.com/dblock).
|
|
12
|
+
|
|
1
13
|
### 1.0.0 (2023/01/10)
|
|
2
14
|
|
|
3
15
|
* [#41](https://github.com/dblock/ruby-enum/pull/41): Make i18n dependency optional - [@peterfication](https://github.com/peterfication).
|
data/Dangerfile
CHANGED
data/Gemfile
CHANGED
|
@@ -8,14 +8,15 @@ gem 'rake'
|
|
|
8
8
|
|
|
9
9
|
group :development, :test do
|
|
10
10
|
gem 'danger'
|
|
11
|
-
gem 'danger-changelog'
|
|
12
|
-
gem 'danger-
|
|
13
|
-
gem '
|
|
14
|
-
gem '
|
|
11
|
+
gem 'danger-changelog'
|
|
12
|
+
gem 'danger-pr-comment'
|
|
13
|
+
gem 'danger-toc'
|
|
14
|
+
gem 'rspec'
|
|
15
|
+
gem 'rubocop', '1.82.1'
|
|
15
16
|
gem 'rubocop-rake'
|
|
16
17
|
gem 'rubocop-rspec'
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
group :test do
|
|
20
|
-
gem '
|
|
21
|
+
gem 'coveralls_reborn', require: false
|
|
21
22
|
end
|
data/Gemfile.lock
CHANGED
|
@@ -1,166 +1,201 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
ruby-enum (1.
|
|
4
|
+
ruby-enum (1.2.0)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: http://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
-
activesupport (
|
|
9
|
+
activesupport (8.1.1)
|
|
10
10
|
base64
|
|
11
11
|
bigdecimal
|
|
12
|
-
concurrent-ruby (~> 1.0, >= 1.
|
|
12
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
13
13
|
connection_pool (>= 2.2.5)
|
|
14
14
|
drb
|
|
15
15
|
i18n (>= 1.6, < 2)
|
|
16
|
+
json
|
|
17
|
+
logger (>= 1.4.2)
|
|
16
18
|
minitest (>= 5.1)
|
|
17
|
-
|
|
18
|
-
tzinfo (~> 2.0)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
securerandom (>= 0.3)
|
|
20
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
21
|
+
uri (>= 0.13.1)
|
|
22
|
+
addressable (2.8.8)
|
|
23
|
+
public_suffix (>= 2.0.2, < 8.0)
|
|
24
|
+
ast (2.4.3)
|
|
25
|
+
base64 (0.3.0)
|
|
26
|
+
bigdecimal (4.0.1)
|
|
24
27
|
claide (1.1.0)
|
|
25
28
|
claide-plugins (0.9.2)
|
|
26
29
|
cork
|
|
27
30
|
nap
|
|
28
31
|
open4 (~> 1.3)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
colored (1.2)
|
|
33
|
+
colored2 (4.0.3)
|
|
34
|
+
concurrent-ruby (1.3.6)
|
|
35
|
+
connection_pool (3.0.2)
|
|
36
|
+
cork (0.2.0)
|
|
37
|
+
colored (~> 1.2)
|
|
38
|
+
coveralls_reborn (0.29.0)
|
|
39
|
+
simplecov (~> 0.22.0)
|
|
40
|
+
term-ansicolor (~> 1.7)
|
|
41
|
+
thor (~> 1.2)
|
|
42
|
+
tins (~> 1.32)
|
|
43
|
+
danger (9.5.3)
|
|
44
|
+
base64 (~> 0.2)
|
|
35
45
|
claide (~> 1.0)
|
|
36
46
|
claide-plugins (>= 0.9.2)
|
|
37
|
-
colored2 (
|
|
47
|
+
colored2 (>= 3.1, < 5)
|
|
38
48
|
cork (~> 0.1)
|
|
39
49
|
faraday (>= 0.9.0, < 3.0)
|
|
40
50
|
faraday-http-cache (~> 2.0)
|
|
41
|
-
git (
|
|
42
|
-
kramdown (
|
|
51
|
+
git (>= 1.13, < 3.0)
|
|
52
|
+
kramdown (>= 2.5.1, < 3.0)
|
|
43
53
|
kramdown-parser-gfm (~> 1.0)
|
|
44
|
-
no_proxy_fix
|
|
45
54
|
octokit (>= 4.0)
|
|
46
|
-
|
|
47
|
-
|
|
55
|
+
pstore (~> 0.1)
|
|
56
|
+
terminal-table (>= 1, < 5)
|
|
57
|
+
danger-changelog (0.8.0)
|
|
48
58
|
danger-plugin-api (~> 1.0)
|
|
49
59
|
danger-plugin-api (1.0.0)
|
|
50
60
|
danger (> 2.0)
|
|
61
|
+
danger-pr-comment (0.1.0)
|
|
62
|
+
danger (~> 9)
|
|
51
63
|
danger-toc (0.2.0)
|
|
52
64
|
activesupport
|
|
53
65
|
danger-plugin-api (~> 1.0)
|
|
54
66
|
kramdown
|
|
55
|
-
diff-lcs (1.
|
|
56
|
-
docile (1.4.
|
|
57
|
-
drb (2.2.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
faraday-http-cache (2.5.0)
|
|
67
|
+
diff-lcs (1.6.2)
|
|
68
|
+
docile (1.4.1)
|
|
69
|
+
drb (2.2.3)
|
|
70
|
+
faraday (2.14.0)
|
|
71
|
+
faraday-net_http (>= 2.0, < 3.5)
|
|
72
|
+
json
|
|
73
|
+
logger
|
|
74
|
+
faraday-http-cache (2.5.1)
|
|
64
75
|
faraday (>= 0.8)
|
|
65
|
-
faraday-net_http (3.
|
|
66
|
-
|
|
76
|
+
faraday-net_http (3.4.2)
|
|
77
|
+
net-http (~> 0.5)
|
|
78
|
+
git (2.3.3)
|
|
79
|
+
activesupport (>= 5.0)
|
|
67
80
|
addressable (~> 2.8)
|
|
81
|
+
process_executer (~> 1.1)
|
|
68
82
|
rchardet (~> 1.8)
|
|
69
|
-
i18n (1.14.
|
|
83
|
+
i18n (1.14.8)
|
|
70
84
|
concurrent-ruby (~> 1.0)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
85
|
+
io-console (0.8.2)
|
|
86
|
+
json (2.18.0)
|
|
87
|
+
kramdown (2.5.1)
|
|
88
|
+
rexml (>= 3.3.9)
|
|
74
89
|
kramdown-parser-gfm (1.1.0)
|
|
75
90
|
kramdown (~> 2.0)
|
|
76
|
-
language_server-protocol (3.17.0.
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
language_server-protocol (3.17.0.5)
|
|
92
|
+
lint_roller (1.1.0)
|
|
93
|
+
logger (1.7.0)
|
|
94
|
+
minitest (6.0.1)
|
|
95
|
+
prism (~> 1.5)
|
|
96
|
+
mize (0.6.1)
|
|
79
97
|
nap (1.1.0)
|
|
80
|
-
|
|
81
|
-
|
|
98
|
+
net-http (0.9.1)
|
|
99
|
+
uri (>= 0.11.1)
|
|
100
|
+
octokit (10.0.0)
|
|
82
101
|
faraday (>= 1, < 3)
|
|
83
102
|
sawyer (~> 0.9)
|
|
84
103
|
open4 (1.3.4)
|
|
85
|
-
parallel (1.
|
|
86
|
-
parser (3.
|
|
104
|
+
parallel (1.27.0)
|
|
105
|
+
parser (3.3.10.0)
|
|
87
106
|
ast (~> 2.4.1)
|
|
88
107
|
racc
|
|
89
|
-
|
|
90
|
-
|
|
108
|
+
prism (1.7.0)
|
|
109
|
+
process_executer (1.3.0)
|
|
110
|
+
pstore (0.2.0)
|
|
111
|
+
public_suffix (7.0.0)
|
|
112
|
+
racc (1.8.1)
|
|
91
113
|
rainbow (3.1.1)
|
|
92
|
-
rake (13.1
|
|
93
|
-
rchardet (1.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
rspec
|
|
101
|
-
rspec-
|
|
102
|
-
|
|
114
|
+
rake (13.3.1)
|
|
115
|
+
rchardet (1.10.0)
|
|
116
|
+
readline (0.0.4)
|
|
117
|
+
reline
|
|
118
|
+
regexp_parser (2.11.3)
|
|
119
|
+
reline (0.6.3)
|
|
120
|
+
io-console (~> 0.5)
|
|
121
|
+
rexml (3.4.4)
|
|
122
|
+
rspec (3.13.2)
|
|
123
|
+
rspec-core (~> 3.13.0)
|
|
124
|
+
rspec-expectations (~> 3.13.0)
|
|
125
|
+
rspec-mocks (~> 3.13.0)
|
|
126
|
+
rspec-core (3.13.6)
|
|
127
|
+
rspec-support (~> 3.13.0)
|
|
128
|
+
rspec-expectations (3.13.5)
|
|
103
129
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
104
|
-
rspec-support (~> 3.
|
|
105
|
-
rspec-mocks (3.
|
|
130
|
+
rspec-support (~> 3.13.0)
|
|
131
|
+
rspec-mocks (3.13.7)
|
|
106
132
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
107
|
-
rspec-support (~> 3.
|
|
108
|
-
rspec-support (3.
|
|
109
|
-
rubocop (1.
|
|
133
|
+
rspec-support (~> 3.13.0)
|
|
134
|
+
rspec-support (3.13.6)
|
|
135
|
+
rubocop (1.82.1)
|
|
110
136
|
json (~> 2.3)
|
|
111
|
-
language_server-protocol (
|
|
137
|
+
language_server-protocol (~> 3.17.0.2)
|
|
138
|
+
lint_roller (~> 1.1.0)
|
|
112
139
|
parallel (~> 1.10)
|
|
113
|
-
parser (>= 3.
|
|
140
|
+
parser (>= 3.3.0.2)
|
|
114
141
|
rainbow (>= 2.2.2, < 4.0)
|
|
115
|
-
regexp_parser (>=
|
|
116
|
-
|
|
117
|
-
rubocop-ast (>= 1.30.0, < 2.0)
|
|
142
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
143
|
+
rubocop-ast (>= 1.48.0, < 2.0)
|
|
118
144
|
ruby-progressbar (~> 1.7)
|
|
119
|
-
unicode-display_width (>= 2.4.0, <
|
|
120
|
-
rubocop-ast (1.
|
|
121
|
-
parser (>= 3.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
rubocop (
|
|
126
|
-
rubocop-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
rubocop (~> 1.40)
|
|
130
|
-
rubocop-capybara (~> 2.17)
|
|
131
|
-
rubocop-factory_bot (~> 2.22)
|
|
145
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
146
|
+
rubocop-ast (1.49.0)
|
|
147
|
+
parser (>= 3.3.7.2)
|
|
148
|
+
prism (~> 1.7)
|
|
149
|
+
rubocop-rake (0.7.1)
|
|
150
|
+
lint_roller (~> 1.1)
|
|
151
|
+
rubocop (>= 1.72.1)
|
|
152
|
+
rubocop-rspec (3.8.0)
|
|
153
|
+
lint_roller (~> 1.1)
|
|
154
|
+
rubocop (~> 1.81)
|
|
132
155
|
ruby-progressbar (1.13.0)
|
|
133
|
-
|
|
134
|
-
sawyer (0.9.2)
|
|
156
|
+
sawyer (0.9.3)
|
|
135
157
|
addressable (>= 2.3.5)
|
|
136
158
|
faraday (>= 0.17.3, < 3)
|
|
159
|
+
securerandom (0.4.1)
|
|
137
160
|
simplecov (0.22.0)
|
|
138
161
|
docile (~> 1.1)
|
|
139
162
|
simplecov-html (~> 0.11)
|
|
140
163
|
simplecov_json_formatter (~> 0.1)
|
|
141
|
-
simplecov-html (0.
|
|
164
|
+
simplecov-html (0.13.2)
|
|
142
165
|
simplecov_json_formatter (0.1.4)
|
|
143
|
-
|
|
144
|
-
|
|
166
|
+
sync (0.5.0)
|
|
167
|
+
term-ansicolor (1.11.3)
|
|
168
|
+
tins (~> 1)
|
|
169
|
+
terminal-table (4.0.0)
|
|
170
|
+
unicode-display_width (>= 1.1.1, < 4)
|
|
171
|
+
thor (1.4.0)
|
|
172
|
+
tins (1.51.0)
|
|
173
|
+
bigdecimal
|
|
174
|
+
mize (~> 0.6)
|
|
175
|
+
readline
|
|
176
|
+
sync
|
|
145
177
|
tzinfo (2.0.6)
|
|
146
178
|
concurrent-ruby (~> 1.0)
|
|
147
|
-
unicode-display_width (2.
|
|
179
|
+
unicode-display_width (3.2.0)
|
|
180
|
+
unicode-emoji (~> 4.1)
|
|
181
|
+
unicode-emoji (4.2.0)
|
|
182
|
+
uri (1.1.1)
|
|
148
183
|
|
|
149
184
|
PLATFORMS
|
|
150
|
-
arm64-darwin-21
|
|
151
185
|
ruby
|
|
152
186
|
|
|
153
187
|
DEPENDENCIES
|
|
188
|
+
coveralls_reborn
|
|
154
189
|
danger
|
|
155
|
-
danger-changelog
|
|
156
|
-
danger-
|
|
190
|
+
danger-changelog
|
|
191
|
+
danger-pr-comment
|
|
192
|
+
danger-toc
|
|
157
193
|
rake
|
|
158
|
-
rspec
|
|
159
|
-
rubocop (
|
|
194
|
+
rspec
|
|
195
|
+
rubocop (= 1.82.1)
|
|
160
196
|
rubocop-rake
|
|
161
197
|
rubocop-rspec
|
|
162
198
|
ruby-enum!
|
|
163
|
-
simplecov
|
|
164
199
|
|
|
165
200
|
BUNDLED WITH
|
|
166
|
-
2.
|
|
201
|
+
2.1.4
|
data/README.md
CHANGED
|
@@ -2,8 +2,8 @@ Ruby::Enum
|
|
|
2
2
|
==========
|
|
3
3
|
|
|
4
4
|
[](http://badge.fury.io/rb/ruby-enum)
|
|
5
|
-
[](https://github.com/dblock/ruby-enum/actions/workflows/test.yml)
|
|
6
|
+
[](https://coveralls.io/github/dblock/ruby-enum?branch=master)
|
|
7
7
|
|
|
8
8
|
Enum-like behavior for Ruby, heavily inspired by [this](http://www.rubyfleebie.com/enumerations-and-ruby), and improved upon [another blog post](http://code.dblock.org/how-to-define-enums-in-ruby).
|
|
9
9
|
|
|
@@ -27,6 +27,7 @@ Enum-like behavior for Ruby, heavily inspired by [this](http://www.rubyfleebie.c
|
|
|
27
27
|
- [Exhaustive case matcher](#exhaustive-case-matcher)
|
|
28
28
|
- [I18n support](#i18n-support)
|
|
29
29
|
- [Benchmarks](#benchmarks)
|
|
30
|
+
- [Performance](#performance)
|
|
30
31
|
- [Contributing](#contributing)
|
|
31
32
|
- [Copyright and License](#copyright-and-license)
|
|
32
33
|
- [Related Projects](#related-projects)
|
|
@@ -232,7 +233,7 @@ The `DuplicateValueError` exception is raised to be consistent with the unique k
|
|
|
232
233
|
|
|
233
234
|
### Inheritance
|
|
234
235
|
|
|
235
|
-
When inheriting from a `Ruby::Enum` class, all defined enums in the parent class will be accessible in
|
|
236
|
+
When inheriting from a `Ruby::Enum` class, all defined enums in the parent class will be accessible in subclasses as well. Subclasses can also provide extra enums, as usual.
|
|
236
237
|
|
|
237
238
|
``` ruby
|
|
238
239
|
class OrderState
|
|
@@ -262,6 +263,26 @@ OrderState.values # ['CREATED', 'PAID']
|
|
|
262
263
|
ShippedOrderState.values # ['CREATED', 'PAID', 'PREPARED', SHIPPED']
|
|
263
264
|
```
|
|
264
265
|
|
|
266
|
+
All other enumerating and hashing methods (`keys`, `key?`, `value?`, `key`, `value`, `to_h`, `parse` and `each`) also consider enums defined anywhere in the class hierarchy.
|
|
267
|
+
|
|
268
|
+
``` ruby
|
|
269
|
+
ShippedOrderState.keys # [:CREATED, :PAID, :PREPARED, :SHIPPED]
|
|
270
|
+
ShippedOrderState.key?(:CREATED) # true
|
|
271
|
+
ShippedOrderState.value(:CREATED) # 'CREATED'
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
A subclass may redefine a key or value already used by a parent class without raising `DuplicateKeyError` or `DuplicateValueError`; its own definition takes precedence.
|
|
275
|
+
|
|
276
|
+
``` ruby
|
|
277
|
+
class ShippedOrderState < OrderState
|
|
278
|
+
define :CREATED, 'RECREATED' # does not raise, overrides the parent class' definition
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
ShippedOrderState::CREATED # 'RECREATED'
|
|
282
|
+
ShippedOrderState.value(:CREATED) # 'RECREATED'
|
|
283
|
+
OrderState.value(:CREATED) # 'CREATED', unaffected
|
|
284
|
+
```
|
|
285
|
+
|
|
265
286
|
### Exhaustive case matcher
|
|
266
287
|
|
|
267
288
|
If you want to make sure that you cover all cases in a case stament, you can use the exhaustive case matcher: `Ruby::Enum::Case`. It will raise an error if a case/enum value is not handled, or if a value is specified that's not part of the enum. This is inspired by the [Rust Pattern Syntax](https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html). If multiple cases match, all matches are being executed. The return value is the value from the matched case, or an array of return values if multiple cases matched.
|
|
@@ -315,9 +336,21 @@ gem "i18n"
|
|
|
315
336
|
Benchmark scripts are defined in the [`benchmarks`](benchmarks) folder and can be run with Rake:
|
|
316
337
|
|
|
317
338
|
```console
|
|
318
|
-
rake
|
|
339
|
+
rake benchmark:basic
|
|
340
|
+
rake benchmark:case
|
|
341
|
+
rake benchmark:inheritance
|
|
319
342
|
```
|
|
320
343
|
|
|
344
|
+
### Performance
|
|
345
|
+
|
|
346
|
+
Constant access (e.g. `Colors::RED`) has no measurable overhead versus a plain Ruby constant, since it's just a constant lookup either way. Basic operations backed by a hash lookup - `value`, `key`, `key?`, `value?`, `keys`, `values` - carry some overhead (roughly 3-5x) compared to using a plain `Hash` directly, due to the extra method dispatch and object wrapping `Ruby::Enum` does internally. Run `rake benchmark:basic` to measure this on your own machine.
|
|
347
|
+
|
|
348
|
+
This overhead is constant regardless of how deep a subclass hierarchy is - `keys`, `key?`, `value?`, `key`, `value`, `to_h`, `parse` and `each` merge and memoize enums inherited from superclasses, so a subclass' lookups are effectively as fast as the base class' (see `rake benchmark:inheritance`).
|
|
349
|
+
|
|
350
|
+
The one notable exception is `Ruby::Enum::Case`, whose exhaustive `case`-like matcher is significantly slower (on the order of 50-100x, see `rake benchmark:case`) than a native Ruby `case`/`when` statement, since it builds and evaluates lambdas on every call rather than being optimized by the Ruby VM. Prefer a native `case` statement in hot code paths and reserve `Ruby::Enum::Case` for cases where its exhaustiveness check is worth the overhead.
|
|
351
|
+
|
|
352
|
+
For most applications this overhead is negligible in absolute terms (low single-digit microseconds per call), but it's worth being aware of in very hot code paths.
|
|
353
|
+
|
|
321
354
|
## Contributing
|
|
322
355
|
|
|
323
356
|
You're encouraged to contribute to ruby-enum. See [CONTRIBUTING](CONTRIBUTING.md) for details.
|
data/RELEASING.md
CHANGED
|
@@ -11,7 +11,7 @@ bundle install
|
|
|
11
11
|
rake
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
Check that the last build succeeded in [
|
|
14
|
+
Check that the last build succeeded in [GitHub Actions](https://github.com/dblock/ruby-enum/actions) for all supported platforms.
|
|
15
15
|
|
|
16
16
|
Add a date to this release in [CHANGELOG.md](CHANGELOG.md).
|
|
17
17
|
|
|
@@ -28,15 +28,24 @@ git add README.md CHANGELOG.md lib/ruby-enum/version.rb
|
|
|
28
28
|
git commit -m "Preparing for release, 0.2.2."
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Release.
|
|
31
|
+
Release. If you have MFA enabled on RubyGems (you should), `rake release` will build the gem, tag it, and push commits/tags to GitHub, but fail at the RubyGems push. Push the gem manually with your OTP.
|
|
32
32
|
|
|
33
33
|
```
|
|
34
34
|
$ rake release
|
|
35
35
|
|
|
36
|
-
ruby-enum
|
|
37
|
-
Tagged
|
|
36
|
+
ruby-enum 1.1.0 built to pkg/ruby-enum-1.1.0.gem.
|
|
37
|
+
Tagged v1.1.0.
|
|
38
38
|
Pushed git commits and tags.
|
|
39
|
-
|
|
39
|
+
...
|
|
40
|
+
You have enabled multi-factor authentication. Please enter OTP code.
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Then push to RubyGems manually:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
$ gem push pkg/ruby-enum-1.1.0.gem --otp <OTP>
|
|
47
|
+
Pushing gem to https://rubygems.org...
|
|
48
|
+
Successfully registered gem: ruby-enum (1.1.0)
|
|
40
49
|
```
|
|
41
50
|
|
|
42
51
|
### Prepare for the Next Version
|
data/Rakefile
CHANGED
|
@@ -18,8 +18,18 @@ RuboCop::RakeTask.new(:rubocop)
|
|
|
18
18
|
task default: %i[rubocop spec]
|
|
19
19
|
|
|
20
20
|
namespace :benchmark do
|
|
21
|
+
desc 'Run benchmark for basic Ruby::Enum operations vs. plain Ruby equivalents'
|
|
22
|
+
task :basic do
|
|
23
|
+
require_relative 'benchmarks/basic'
|
|
24
|
+
end
|
|
25
|
+
|
|
21
26
|
desc 'Run benchmark for the Ruby::Enum::Case'
|
|
22
27
|
task :case do
|
|
23
28
|
require_relative 'benchmarks/case'
|
|
24
29
|
end
|
|
30
|
+
|
|
31
|
+
desc 'Run benchmark for enum lookups on classes with inheritance'
|
|
32
|
+
task :inheritance do
|
|
33
|
+
require_relative 'benchmarks/inheritance'
|
|
34
|
+
end
|
|
25
35
|
end
|
data/UPGRADING.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Upgrading Ruby::Enum
|
|
2
2
|
|
|
3
|
+
## Upgrading to >= 1.2.0
|
|
4
|
+
|
|
5
|
+
### Inheritance & `keys`, `key?`, `value?`, `key`, `value`, `to_h`, `parse` and `each`
|
|
6
|
+
|
|
7
|
+
This only applies to classes that inherit from another which is a `Ruby::Enum`.
|
|
8
|
+
|
|
9
|
+
Prior to version `1.2.0`, only `values` enumerated enums defined in the entire class hierarchy; `keys`, `key?`, `value?`, `key`, `value`, `to_h`, `parse` and `each` only considered enums defined directly on the class, silently ignoring anything defined in a superclass.
|
|
10
|
+
|
|
11
|
+
As of version `1.2.0`, these methods behave consistently with `values` and also enumerate/consider enums defined anywhere in the class hierarchy, ancestors first. A subclass may still redefine a key or value already used by a superclass; its own definition takes precedence.
|
|
12
|
+
|
|
13
|
+
``` ruby
|
|
14
|
+
class PrimaryColors
|
|
15
|
+
include Ruby::Enum
|
|
16
|
+
|
|
17
|
+
define :RED, 'RED'
|
|
18
|
+
define :GREEN, 'GREEN'
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class RainbowColors < PrimaryColors
|
|
22
|
+
define :ORANGE, 'ORANGE'
|
|
23
|
+
end
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`gem 'ruby-enum', '< 1.2.0'`
|
|
27
|
+
|
|
28
|
+
``` ruby
|
|
29
|
+
RainbowColors.keys # => [:ORANGE]
|
|
30
|
+
RainbowColors.key?(:RED) # => false
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`gem 'ruby-enum', '>= 1.2.0'`
|
|
34
|
+
|
|
35
|
+
``` ruby
|
|
36
|
+
RainbowColors.keys # => [:RED, :GREEN, :ORANGE]
|
|
37
|
+
RainbowColors.key?(:RED) # => true
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
See [#49](https://github.com/dblock/ruby-enum/issues/49) for more information.
|
|
41
|
+
|
|
3
42
|
## Upgrading to >= 0.9.0
|
|
4
43
|
|
|
5
44
|
### Inheritance & `Ruby::Enum.values`
|
data/benchmarks/basic.rb
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
4
|
+
|
|
5
|
+
require 'benchmark'
|
|
6
|
+
require 'ruby-enum'
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Ruby::Enum equivalent of a plain Hash/constant lookup.
|
|
10
|
+
class Colors
|
|
11
|
+
include Ruby::Enum
|
|
12
|
+
|
|
13
|
+
define :RED, 'red'
|
|
14
|
+
define :GREEN, 'green'
|
|
15
|
+
define :BLUE, 'blue'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Plain Ruby equivalents, doing the same lookups without Ruby::Enum.
|
|
19
|
+
PLAIN_HASH = { RED: 'red', GREEN: 'green', BLUE: 'blue' }.freeze
|
|
20
|
+
|
|
21
|
+
module PlainConstants
|
|
22
|
+
RED = 'red'
|
|
23
|
+
GREEN = 'green'
|
|
24
|
+
BLUE = 'blue'
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
n = 1_000_000
|
|
28
|
+
|
|
29
|
+
def benchmark(label, iterations, &block)
|
|
30
|
+
time = Benchmark.realtime { iterations.times(&block) }
|
|
31
|
+
puts "#{label}: #{time.round(4)}"
|
|
32
|
+
time
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
puts "Running #{n} iterations of each scenario below\n\n"
|
|
36
|
+
|
|
37
|
+
puts '--- Constant access ---'
|
|
38
|
+
enum_const_time = benchmark('Ruby::Enum constant (Colors::RED)', n) { Colors::RED }
|
|
39
|
+
plain_const_time = benchmark('plain Ruby constant (PlainConstants::RED)', n) { PlainConstants::RED }
|
|
40
|
+
|
|
41
|
+
puts "\n--- Key to value lookup ---"
|
|
42
|
+
enum_value_time = benchmark('Ruby::Enum (Colors.value(:RED))', n) { Colors.value(:RED) }
|
|
43
|
+
hash_value_time = benchmark('plain Hash (PLAIN_HASH[:RED])', n) { PLAIN_HASH[:RED] }
|
|
44
|
+
|
|
45
|
+
puts "\n--- Value to key lookup ---"
|
|
46
|
+
benchmark('Ruby::Enum (Colors.key(\'red\'))', n) { Colors.key('red') }
|
|
47
|
+
benchmark('plain Hash (PLAIN_HASH.key(\'red\'))', n) { PLAIN_HASH.key('red') }
|
|
48
|
+
|
|
49
|
+
puts "\n--- Existence checks ---"
|
|
50
|
+
benchmark('Ruby::Enum (Colors.key?(:RED))', n) { Colors.key?(:RED) }
|
|
51
|
+
benchmark('plain Hash (PLAIN_HASH.key?(:RED))', n) { PLAIN_HASH.key?(:RED) }
|
|
52
|
+
|
|
53
|
+
puts "\n--- Enumerating all keys/values ---"
|
|
54
|
+
benchmark('Ruby::Enum (Colors.keys)', n) { Colors.keys }
|
|
55
|
+
benchmark('plain Hash (PLAIN_HASH.keys)', n) { PLAIN_HASH.keys }
|
|
56
|
+
benchmark('Ruby::Enum (Colors.values)', n) { Colors.values }
|
|
57
|
+
benchmark('plain Hash (PLAIN_HASH.values)', n) { PLAIN_HASH.values }
|
|
58
|
+
|
|
59
|
+
puts "\n--- Comparison ---"
|
|
60
|
+
puts "Ruby::Enum constant access is #{(enum_const_time / plain_const_time).round(2)}x plain Ruby constant access"
|
|
61
|
+
puts "Ruby::Enum .value is #{(enum_value_time / hash_value_time).round(2)}x plain Hash#[]"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
4
|
+
|
|
5
|
+
require 'benchmark'
|
|
6
|
+
require 'ruby-enum'
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
# Base enum, no inheritance.
|
|
10
|
+
class Colors
|
|
11
|
+
include Ruby::Enum
|
|
12
|
+
|
|
13
|
+
define :RED, 'red'
|
|
14
|
+
define :GREEN, 'green'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
##
|
|
18
|
+
# Subclass, adds its own enum on top of an inherited one (1 level).
|
|
19
|
+
class SubColors < Colors
|
|
20
|
+
define :BLUE, 'blue'
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
##
|
|
24
|
+
# Sub-subclass, adds its own enum on top of 2 inherited levels.
|
|
25
|
+
class SubSubColors < SubColors
|
|
26
|
+
define :YELLOW, 'yellow'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
n = 1_000_000
|
|
30
|
+
|
|
31
|
+
def benchmark(label, iterations, &block)
|
|
32
|
+
time = Benchmark.realtime { iterations.times(&block) }
|
|
33
|
+
puts "#{label}: #{time.round(4)}"
|
|
34
|
+
time
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
puts "Running #{n} iterations of each scenario below\n\n"
|
|
38
|
+
|
|
39
|
+
puts '--- .value lookups, by depth of inheritance ---'
|
|
40
|
+
base_value = benchmark('base class (no inheritance)', n) { Colors.value(:RED) }
|
|
41
|
+
sub_value = benchmark('subclass (1 level)', n) { SubColors.value(:RED) }
|
|
42
|
+
sub_sub_value = benchmark('sub-subclass (2 levels)', n) { SubSubColors.value(:RED) }
|
|
43
|
+
|
|
44
|
+
puts "\n--- Other methods on a subclass (1 level) ---"
|
|
45
|
+
benchmark('.keys', n) { SubColors.keys }
|
|
46
|
+
benchmark('.key?', n) { SubColors.key?(:RED) }
|
|
47
|
+
benchmark('.to_h', n) { SubColors.to_h }
|
|
48
|
+
count = 0
|
|
49
|
+
benchmark('.each', n) { SubColors.each { |_k, _v| count += 1 } }
|
|
50
|
+
|
|
51
|
+
puts "\n--- Comparison ---"
|
|
52
|
+
puts "subclass value is #{(sub_value / base_value).round(2)}x base class value"
|
|
53
|
+
puts "sub-subclass value is #{(sub_sub_value / base_value).round(2)}x base class value"
|