typesafe_enum 0.2.2 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: