typesafe_enum 0.2.2 → 0.3.1

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.
@@ -0,0 +1,11 @@
1
+ require 'ci/reporter/rake/rspec'
2
+
3
+ # Configure CI::Reporter report generation
4
+ ENV['GENERATE_REPORTS'] ||= 'true'
5
+ ENV['CI_REPORTS'] = 'artifacts/rspec'
6
+
7
+ desc 'Run all specs in spec directory, with coverage'
8
+ task coverage: ['ci:setup:rspec'] do
9
+ ENV['COVERAGE'] ||= 'true'
10
+ Rake::Task[:spec].invoke
11
+ end
data/rakelib/gem.rake ADDED
@@ -0,0 +1,54 @@
1
+ require 'rubygems/gem_runner'
2
+ require 'typesafe_enum/module_info'
3
+
4
+ gem_root_module = TypesafeEnum
5
+
6
+ class << gem_root_module
7
+ def project_root
8
+ @project_root ||= File.expand_path('..', __dir__)
9
+ end
10
+
11
+ def artifacts_dir
12
+ return project_root unless ENV['CI']
13
+
14
+ @artifacts_dir ||= File.join(project_root, 'artifacts')
15
+ end
16
+
17
+ def gemspec_file
18
+ @gemspec_file ||= begin
19
+ gemspec_files = Dir.glob(File.expand_path('*.gemspec', project_root))
20
+ raise ArgumentError, "Too many .gemspecs: #{gemspec_files.join(', ')}" if gemspec_files.size > 1
21
+ raise ArgumentError, 'No .gemspec file found' if gemspec_files.empty?
22
+
23
+ gemspec_files[0]
24
+ end
25
+ end
26
+
27
+ def gemspec_basename
28
+ File.basename(gemspec_file)
29
+ end
30
+
31
+ def output_file
32
+ @output_file ||= begin
33
+ gem_name = File.basename(gemspec_file, '.*')
34
+ version = self::ModuleInfo::VERSION
35
+ basename = "#{gem_name}-#{version}.gem"
36
+ File.join(artifacts_dir, basename)
37
+ end
38
+ end
39
+
40
+ def output_file_relative
41
+ return File.basename(output_file) unless ENV['CI']
42
+
43
+ @output_file_relative ||= begin
44
+ artifacts_dir_relative = File.basename(artifacts_dir)
45
+ File.join(artifacts_dir_relative, File.basename(output_file))
46
+ end
47
+ end
48
+ end
49
+
50
+ desc "Build #{gem_root_module.gemspec_basename} as #{gem_root_module.output_file_relative}"
51
+ task :gem do
52
+ args = ['build', gem_root_module.gemspec_file, "--output=#{gem_root_module.output_file}"]
53
+ Gem::GemRunner.new.run(args)
54
+ end
@@ -0,0 +1,18 @@
1
+ require 'rubocop'
2
+ require 'rubocop/rake_task'
3
+
4
+ desc 'Run rubocop with HTML output'
5
+ RuboCop::RakeTask.new(:rubocop) do |cop|
6
+ output = ENV['RUBOCOP_OUTPUT'] || 'artifacts/rubocop/index.html'
7
+ puts "Writing RuboCop inspection report to #{output}"
8
+
9
+ cop.verbose = false
10
+ cop.formatters = ['html']
11
+ cop.options = ['--out', output]
12
+ end
13
+
14
+ desc 'Run RuboCop with auto-correct, and output results to console'
15
+ task :ra do
16
+ # b/c we want console output, we can't just use `rubocop:auto_correct`
17
+ RuboCop::CLI.new.run(['--safe-auto-correct'])
18
+ end
data/rakelib/spec.rake ADDED
@@ -0,0 +1,2 @@
1
+ require 'rspec/core/rake_task'
2
+ RSpec::Core::RakeTask.new(:spec)
data/spec/.rubocop.yml CHANGED
@@ -1,5 +1,8 @@
1
1
  inherit_from: ../.rubocop.yml
2
2
 
3
+ Lint/ConstantDefinitionInBlock:
4
+ Enabled: false
5
+
3
6
  Style/ClassAndModuleChildren:
4
7
  Enabled: false
5
8
 
@@ -29,6 +29,19 @@ class Scale < TypesafeEnum::Base
29
29
  new :MEGA, 1_000_000
30
30
  end
31
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
+
39
+ module Super
40
+ module Modular
41
+ class Enum < TypesafeEnum::Base; end
42
+ end
43
+ end
44
+
32
45
  module TypesafeEnum
33
46
  describe Base do
34
47
 
@@ -38,6 +51,15 @@ module TypesafeEnum
38
51
  expect(enum).to be_a(Suit)
39
52
  end
40
53
 
54
+ it 'allows nil values' do
55
+ expect do
56
+ class ::NilValues < Base
57
+ new :NONE, nil
58
+ end
59
+ end.not_to raise_error
60
+ expect(::NilValues.to_a).not_to be_empty
61
+ end
62
+
41
63
  it 'insists symbols be symbols' do
42
64
  expect do
43
65
  class ::StringKeys < Base
@@ -80,6 +102,18 @@ module TypesafeEnum
80
102
  expect(::DuplicateValues.find_by_key(:ALSO_SPADES)).to be_nil
81
103
  end
82
104
 
105
+ it 'disallows duplicate nil values' do
106
+ expect do
107
+ class ::DuplicateNilValues < Base
108
+ new :NONE, nil
109
+ new :NULL, nil
110
+ end.to raise_error(NameError)
111
+ expect(::DuplicateNilValues.to_a).to eq([::DuplicateNilValues::NONE])
112
+ expect(::DuplicateNilValues::NONE.value).to be_nil
113
+ expect(::DuplicateNilValues.find_by_key(:NULL)).to be_nil
114
+ end
115
+ end
116
+
83
117
  it 'disallows nil keys' do
84
118
  expect do
85
119
  class ::NilKeys < Base
@@ -93,8 +127,8 @@ module TypesafeEnum
93
127
  class ::IdenticalInstances < Base
94
128
  new :SPADES, 'spades'
95
129
  end
96
- expected_msg = /ignoring redeclaration of IdenticalInstances::SPADES with value spades/
97
- expect(::IdenticalInstances).to receive(:warn).with(a_string_matching(expected_msg))
130
+ expected_msg = /ignoring redeclaration of IdenticalInstances::SPADES with value "spades" \(source: .*base_spec.rb:[0-9]+:in `new'\)/
131
+ expect(::IdenticalInstances).to receive(:warn).once.with(expected_msg)
98
132
  class ::IdenticalInstances < Base
99
133
  new :SPADES, 'spades'
100
134
  end
@@ -111,6 +145,31 @@ module TypesafeEnum
111
145
  it 'is private' do
112
146
  expect { Tarot.new(:PENTACLES) }.to raise_error(NoMethodError)
113
147
  end
148
+
149
+ it 'can be overridden' do
150
+ class ::Extras < Base
151
+ attr_reader :x1
152
+ attr_reader :x2
153
+
154
+ def initialize(key, x1, x2)
155
+ super(key)
156
+ @x1 = x1
157
+ @x2 = x2
158
+ end
159
+
160
+ new(:AB, 'a', 'b') do
161
+ def x3
162
+ 'c'
163
+ end
164
+ end
165
+ end
166
+
167
+ expect(Extras::AB.key).to eq(:AB)
168
+ expect(Extras::AB.value).to eq('ab')
169
+ expect(Extras::AB.x1).to eq('a')
170
+ expect(Extras::AB.x2).to eq('b')
171
+ expect(Extras::AB.x3).to eq('c')
172
+ end
114
173
  end
115
174
 
116
175
  describe :to_a do
@@ -126,13 +185,13 @@ module TypesafeEnum
126
185
  end
127
186
 
128
187
  describe :size do
129
- it 'returns the number of enum instnaces' do
188
+ it 'returns the number of enum instances' do
130
189
  expect(Suit.size).to eq(4)
131
190
  end
132
191
  end
133
192
 
134
193
  describe :count do
135
- it 'returns the number of enum instnaces' do
194
+ it 'returns the number of enum instances' do
136
195
  expect(Suit.count).to eq(4)
137
196
  end
138
197
 
@@ -146,7 +205,7 @@ module TypesafeEnum
146
205
  end
147
206
 
148
207
  describe :each do
149
- it 'iterates the enum values' do
208
+ it 'iterates the enum instances' do
150
209
  expected = [Suit::CLUBS, Suit::DIAMONDS, Suit::HEARTS, Suit::SPADES]
151
210
  index = 0
152
211
  Suit.each do |s|
@@ -156,6 +215,42 @@ module TypesafeEnum
156
215
  end
157
216
  end
158
217
 
218
+ describe :keys do
219
+ it 'returns all keys of all instances' do
220
+ expect(Suit.keys).to eq(%i[CLUBS DIAMONDS HEARTS SPADES])
221
+ end
222
+ end
223
+
224
+ describe :values do
225
+ it 'returns all values of all instances' do
226
+ expect(Suit.values).to eq(%w[clubs diamonds hearts spades])
227
+ end
228
+
229
+ end
230
+
231
+ describe :each_key do
232
+ it 'iterates the enum keys' do
233
+ expected = %i[CLUBS DIAMONDS HEARTS SPADES]
234
+ index = 0
235
+ Suit.each_key do |s|
236
+ expect(s).to eq(expected[index])
237
+ index += 1
238
+ end
239
+ end
240
+
241
+ end
242
+
243
+ describe :each_value do
244
+ it 'iterates the enum values' do
245
+ expected = %w[clubs diamonds hearts spades]
246
+ index = 0
247
+ Suit.each_value do |s|
248
+ expect(s).to eq(expected[index])
249
+ index += 1
250
+ end
251
+ end
252
+ end
253
+
159
254
  describe :each_with_index do
160
255
  it 'iterates the enum values with indices' do
161
256
  expected = [Suit::CLUBS, Suit::DIAMONDS, Suit::HEARTS, Suit::SPADES]
@@ -302,6 +397,20 @@ module TypesafeEnum
302
397
  expect(s.value).to eq(expected[index])
303
398
  end
304
399
  end
400
+
401
+ it 'returns an explicit value' do
402
+ expected = [10, 100, 1000, 1_000_000]
403
+ Scale.each_with_index do |s, index|
404
+ expect(s.value).to eq(expected[index])
405
+ end
406
+ end
407
+
408
+ it 'supports nil values' do
409
+ expected = ['http', 'https', 'example', nil]
410
+ Scheme.each_with_index do |s, index|
411
+ expect(s.value).to eq(expected[index])
412
+ end
413
+ end
305
414
  end
306
415
 
307
416
  describe :key do
@@ -324,10 +433,10 @@ module TypesafeEnum
324
433
  describe :to_s do
325
434
  it 'provides an informative string' do
326
435
  aggregate_failures 'informative string' do
327
- [Suit, Tarot, RGBColor, Scale].each do |ec|
436
+ [Suit, Tarot, RGBColor, Scale, Scheme].each do |ec|
328
437
  ec.each do |ev|
329
438
  result = ev.to_s
330
- [ec.to_s, ev.key, ev.ord, ev.value].each do |info|
439
+ [ec.to_s, ev.key, ev.ord, ev.value.inspect].each do |info|
331
440
  expect(result).to include(info.to_s)
332
441
  end
333
442
  end
@@ -374,6 +483,44 @@ module TypesafeEnum
374
483
  expect(Scale.find_by_value(s.value)).to be(s)
375
484
  end
376
485
  end
486
+
487
+ it 'supports enums with explicit nil values' do
488
+ Scheme.each do |s|
489
+ expect(Scheme.find_by_value(s.value)).to be(s)
490
+ end
491
+ end
492
+ end
493
+
494
+ describe :find_by_value! do
495
+ it 'maps values to enum instances' do
496
+ values = %w[clubs diamonds hearts spades]
497
+ expected = Suit.to_a
498
+ values.each_with_index do |n, index|
499
+ expect(Suit.find_by_value!(n)).to be(expected[index])
500
+ end
501
+ end
502
+
503
+ it 'throws EnumValidationError for invalid values' do
504
+ expect { Suit.find_by_value!('wands') }.to raise_error(Exceptions::EnumValidationError)
505
+ end
506
+
507
+ it 'supports enums with symbol values' do
508
+ RGBColor.each do |c|
509
+ expect(RGBColor.find_by_value!(c.value)).to be(c)
510
+ end
511
+ end
512
+
513
+ it 'supports enums with integer values' do
514
+ Scale.each do |s|
515
+ expect(Scale.find_by_value!(s.value)).to be(s)
516
+ end
517
+ end
518
+
519
+ it 'supports enums with explicit nil values' do
520
+ Scheme.each do |s|
521
+ expect(Scheme.find_by_value!(s.value)).to be(s)
522
+ end
523
+ end
377
524
  end
378
525
 
379
526
  describe :find_by_value_str do
@@ -400,6 +547,44 @@ module TypesafeEnum
400
547
  expect(Scale.find_by_value_str(s.value.to_s)).to be(s)
401
548
  end
402
549
  end
550
+
551
+ it 'supports enums with explicit nil values' do
552
+ Scheme.each do |s|
553
+ expect(Scheme.find_by_value_str(s.value)).to be(s)
554
+ end
555
+ end
556
+ end
557
+
558
+ describe :find_by_value_str! do
559
+ it 'maps string values to enum instances' do
560
+ values = %w[clubs diamonds hearts spades]
561
+ expected = Suit.to_a
562
+ values.each_with_index do |n, index|
563
+ expect(Suit.find_by_value_str!(n)).to be(expected[index])
564
+ end
565
+ end
566
+
567
+ it 'throws EnumValidationError for invalid values' do
568
+ expect { Suit.find_by_value_str!('wands') }.to raise_error(Exceptions::EnumValidationError)
569
+ end
570
+
571
+ it 'supports enums with symbol values' do
572
+ RGBColor.each do |c|
573
+ expect(RGBColor.find_by_value_str!(c.value.to_s)).to be(c)
574
+ end
575
+ end
576
+
577
+ it 'supports enums with integer values' do
578
+ Scale.each do |s|
579
+ expect(Scale.find_by_value_str!(s.value.to_s)).to be(s)
580
+ end
581
+ end
582
+
583
+ it 'supports enums with explicit nil values' do
584
+ Scheme.each do |s|
585
+ expect(Scheme.find_by_value_str!(s.value)).to be(s)
586
+ end
587
+ end
403
588
  end
404
589
 
405
590
  describe :find_by_ord do
@@ -422,6 +607,13 @@ module TypesafeEnum
422
607
  end
423
608
  end
424
609
 
610
+ describe :class_name do
611
+ it 'returns the demodulized class name' do
612
+ expect(Super::Modular::Enum.send(:class_name)).to eq 'Enum'
613
+ expect(Suit.send(:class_name)).to eq 'Suit'
614
+ end
615
+ end
616
+
425
617
  it 'supports case statements' do
426
618
  def pip(suit)
427
619
  case suit
@@ -7,10 +7,10 @@ require 'uri'
7
7
  require 'typesafe_enum/module_info'
8
8
 
9
9
  Gem::Specification.new do |spec|
10
- spec.name = TypesafeEnum::NAME
11
- spec.version = TypesafeEnum::VERSION
10
+ spec.name = TypesafeEnum::ModuleInfo::NAME
11
+ spec.version = TypesafeEnum::ModuleInfo::VERSION
12
12
  spec.authors = ['David Moles']
13
- spec.email = ['david.moles@ucop.edu']
13
+ spec.email = ['dmoles@berkeley.edu']
14
14
  spec.summary = 'Typesafe enum pattern for Ruby'
15
15
  spec.description = 'A gem that implements the typesafe enum pattern in Ruby'
16
16
  spec.license = 'MIT'
@@ -23,9 +23,13 @@ Gem::Specification.new do |spec|
23
23
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
24
  spec.require_paths = ['lib']
25
25
 
26
- spec.add_development_dependency 'rake', '~> 12.3', '>= 12.3.3'
26
+ spec.required_ruby_version = '>= 2.7'
27
+
28
+ spec.add_development_dependency 'ci_reporter_rspec', '~> 1.0'
29
+ spec.add_development_dependency 'colorize', '~> 0.8'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
27
31
  spec.add_development_dependency 'rspec', '~> 3.9'
28
- spec.add_development_dependency 'rubocop', '~> 0.80'
32
+ spec.add_development_dependency 'rubocop', '0.91'
29
33
  spec.add_development_dependency 'simplecov', '~> 0.18'
30
34
  spec.add_development_dependency 'simplecov-console', '~> 0.7'
31
35
  spec.add_development_dependency 'yard', '~> 0.9', '>= 0.9.12'
metadata CHANGED
@@ -1,35 +1,57 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typesafe_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Moles
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-04-24 00:00:00.000000000 Z
11
+ date: 2022-11-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: rake
14
+ name: ci_reporter_rspec
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '12.3'
20
- - - ">="
19
+ version: '1.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
21
25
  - !ruby/object:Gem::Version
22
- version: 12.3.3
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.8'
23
34
  type: :development
24
35
  prerelease: false
25
36
  version_requirements: !ruby/object:Gem::Requirement
26
37
  requirements:
27
38
  - - "~>"
28
39
  - !ruby/object:Gem::Version
29
- version: '12.3'
30
- - - ">="
40
+ version: '0.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
31
46
  - !ruby/object:Gem::Version
32
- version: 12.3.3
47
+ version: '13.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '13.0'
33
55
  - !ruby/object:Gem::Dependency
34
56
  name: rspec
35
57
  requirement: !ruby/object:Gem::Requirement
@@ -48,16 +70,16 @@ dependencies:
48
70
  name: rubocop
49
71
  requirement: !ruby/object:Gem::Requirement
50
72
  requirements:
51
- - - "~>"
73
+ - - '='
52
74
  - !ruby/object:Gem::Version
53
- version: '0.80'
75
+ version: '0.91'
54
76
  type: :development
55
77
  prerelease: false
56
78
  version_requirements: !ruby/object:Gem::Requirement
57
79
  requirements:
58
- - - "~>"
80
+ - - '='
59
81
  - !ruby/object:Gem::Version
60
- version: '0.80'
82
+ version: '0.91'
61
83
  - !ruby/object:Gem::Dependency
62
84
  name: simplecov
63
85
  requirement: !ruby/object:Gem::Requirement
@@ -108,12 +130,22 @@ dependencies:
108
130
  version: 0.9.12
109
131
  description: A gem that implements the typesafe enum pattern in Ruby
110
132
  email:
111
- - david.moles@ucop.edu
133
+ - dmoles@berkeley.edu
112
134
  executables: []
113
135
  extensions: []
114
136
  extra_rdoc_files: []
115
137
  files:
138
+ - ".github/workflows/build.yml"
116
139
  - ".gitignore"
140
+ - ".idea/.rakeTasks"
141
+ - ".idea/codeStyles/Project.xml"
142
+ - ".idea/codeStyles/codeStyleConfig.xml"
143
+ - ".idea/go.imports.xml"
144
+ - ".idea/inspectionProfiles/Project_Default.xml"
145
+ - ".idea/misc.xml"
146
+ - ".idea/modules.xml"
147
+ - ".idea/typesafe_enum.iml"
148
+ - ".idea/vcs.xml"
117
149
  - ".rubocop.yml"
118
150
  - ".ruby-version"
119
151
  - ".travis.yml"
@@ -125,7 +157,13 @@ files:
125
157
  - Rakefile
126
158
  - lib/typesafe_enum.rb
127
159
  - lib/typesafe_enum/base.rb
160
+ - lib/typesafe_enum/class_methods.rb
161
+ - lib/typesafe_enum/exceptions.rb
128
162
  - lib/typesafe_enum/module_info.rb
163
+ - rakelib/coverage.rake
164
+ - rakelib/gem.rake
165
+ - rakelib/rubocop.rake
166
+ - rakelib/spec.rake
129
167
  - spec/.rubocop.yml
130
168
  - spec/spec_helper.rb
131
169
  - spec/unit/typesafe_enum/base_spec.rb
@@ -134,7 +172,7 @@ homepage: https://github.com/dmolesUC/typesafe_enum
134
172
  licenses:
135
173
  - MIT
136
174
  metadata: {}
137
- post_install_message:
175
+ post_install_message:
138
176
  rdoc_options: []
139
177
  require_paths:
140
178
  - lib
@@ -142,15 +180,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
180
  requirements:
143
181
  - - ">="
144
182
  - !ruby/object:Gem::Version
145
- version: '0'
183
+ version: '2.7'
146
184
  required_rubygems_version: !ruby/object:Gem::Requirement
147
185
  requirements:
148
186
  - - ">="
149
187
  - !ruby/object:Gem::Version
150
188
  version: '0'
151
189
  requirements: []
152
- rubygems_version: 3.0.8
153
- signing_key:
190
+ rubygems_version: 3.1.6
191
+ signing_key:
154
192
  specification_version: 4
155
193
  summary: Typesafe enum pattern for Ruby
156
194
  test_files: