literal_enums 1.1.1 → 2.0.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/.github/FUNDING.yml +3 -0
- data/.github/workflows/ci.yml +29 -0
- data/.gitignore +2 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile +7 -3
- data/README.md +15 -43
- data/bench.rb +18 -0
- data/lib/enum.rb +58 -21
- data/lib/literal_enums/transitions.rb +16 -18
- data/lib/literal_enums/version.rb +1 -1
- data/lib/literal_enums.rb +3 -5
- data/literal_enums.gemspec +2 -5
- metadata +8 -61
- data/.github/workflows/ruby.yml +0 -24
- data/Gemfile.lock +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b7e6724b81f59fbf8d701b0567dc17c344c53c677c318992a7a799acf3242c05
|
4
|
+
data.tar.gz: 735a34d71b23525d8285e4fccb39063946ba1af6ff691081471d9b14f869bc40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4331f3a30ca04be1eb49fb20463a673eb36a9a721fab8ae7fd0fb8ecab1a1c37d0ba9e43b34b20416230f43fac8f3c738cfff0127b4cfdc8feb3a5d30f1ea064
|
7
|
+
data.tar.gz: d25213819f531fb985c7556171a8fc4820d87672f7bad03a41c1cdda26cb7c20c0974db96f832016aba3251a1581337f0000aebe7c4a00fb128884266e67de19
|
data/.github/FUNDING.yml
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ main ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ main ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
tests:
|
11
|
+
strategy:
|
12
|
+
matrix:
|
13
|
+
os: ['ubuntu-latest', 'macos-latest']
|
14
|
+
ruby-version: ['2.7', '3.0', '3.1', 'head']
|
15
|
+
runs-on: ${{ matrix.os }}
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v3
|
18
|
+
|
19
|
+
- name: Setup
|
20
|
+
uses: ruby/setup-ruby@v1
|
21
|
+
with:
|
22
|
+
ruby-version: ${{ matrix.ruby-version }}
|
23
|
+
bundler-cache: false
|
24
|
+
|
25
|
+
- name: Install dependencies
|
26
|
+
run: bundle install
|
27
|
+
|
28
|
+
- name: Tests
|
29
|
+
run: bundle exec rake
|
data/.gitignore
CHANGED
data/CODE_OF_CONDUCT.md
CHANGED
@@ -55,7 +55,7 @@ further defined and clarified by project maintainers.
|
|
55
55
|
## Enforcement
|
56
56
|
|
57
57
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
-
reported by contacting the project team at joel
|
58
|
+
reported by contacting the project team at joel@drapper.me. All
|
59
59
|
complaints will be reviewed and investigated and will result in a response that
|
60
60
|
is deemed necessary and appropriate to the circumstances. The project team is
|
61
61
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
data/Gemfile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
source "https://rubygems.org"
|
4
|
+
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
4
5
|
|
5
|
-
# Specify your gem's dependencies in literal_enums.gemspec
|
6
6
|
gemspec
|
7
|
+
|
8
|
+
gem "rake"
|
9
|
+
gem "minitest"
|
10
|
+
gem "benchmark-ips"
|
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
This documentation is for Literal Enums 2.0, which is not yet supported by Literal Enums Rails. You can see documentaiton for Literal Enums v1 [here](https://github.com/joeldrapper/literal_enums/tree/d49eeba40f01f24c6b26d4dcdc6abb0da28e9ccb#readme).
|
2
|
+
|
1
3
|
# literal_enums
|
2
4
|
|
3
5
|
Literal Enums makes Enumerations first-class citizens in Ruby, providing a literal definition syntax.
|
@@ -8,9 +10,9 @@ You can define an enum by subclassing `Enum` and using the literal syntax.
|
|
8
10
|
|
9
11
|
```ruby
|
10
12
|
class Color < Enum
|
11
|
-
Red
|
12
|
-
Green
|
13
|
-
Blue
|
13
|
+
Red
|
14
|
+
Green
|
15
|
+
Blue
|
14
16
|
end
|
15
17
|
```
|
16
18
|
|
@@ -20,7 +22,7 @@ Here we’ve enumerated `Color::Red`, `Color::Green`, and `Color::Blue` constant
|
|
20
22
|
Color::Red.is_a?(Color) # returns true
|
21
23
|
```
|
22
24
|
|
23
|
-
Enum classes have synthetic methods for looking up their members. `Color.members` will return
|
25
|
+
Enum classes have synthetic methods for looking up their members. `Color.members` will return an `Array` of members of the `Color` enumeration: `Color::Red`, `Color::Green`, and `Color::Blue`.
|
24
26
|
|
25
27
|
Members also have polymorphic predicate methods for each member of the enumeration in lower-snake-case.
|
26
28
|
|
@@ -46,7 +48,7 @@ end
|
|
46
48
|
Then we can look up all the values.
|
47
49
|
|
48
50
|
```ruby
|
49
|
-
Color.values # returns
|
51
|
+
Color.values # returns an Array of ["ff0000", "00ff00", "0000f"].
|
50
52
|
```
|
51
53
|
|
52
54
|
We can also look at the value for any member directly.
|
@@ -90,50 +92,20 @@ It is also possible to define a more complex state machine by defining `transiti
|
|
90
92
|
|
91
93
|
```ruby
|
92
94
|
class State < Enum
|
93
|
-
Pending
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
Approved do
|
100
|
-
def transitions_to
|
101
|
-
Published
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
Rejected do
|
106
|
-
def transitions_to
|
107
|
-
Deleted
|
108
|
-
end
|
109
|
-
end
|
95
|
+
Pending -> { [Approved, Rejected] }
|
96
|
+
Approved -> { Published }
|
97
|
+
Rejected -> { Deleted }
|
110
98
|
|
111
|
-
Deleted
|
112
|
-
Published
|
99
|
+
Deleted
|
100
|
+
Published
|
113
101
|
end
|
114
102
|
```
|
115
103
|
|
116
|
-
Given the above definition, we can transition from one state to another by calling
|
117
|
-
|
118
|
-
```ruby
|
119
|
-
State::Pending.transition_to(State::Approved) # returns State::Approved.
|
120
|
-
State::Pending.transition_to(State::Published) # raises a LiteralEnums::TransitionError.
|
121
|
-
```
|
122
|
-
|
123
|
-
Alternatively, we can call the new state as a method on the old state.
|
124
|
-
|
125
|
-
```ruby
|
126
|
-
State::Pending.approved # returns State::Approved.
|
127
|
-
```
|
128
|
-
|
129
|
-
An invalid transition would return a `NoMethodErorr` in this case as the method is not defined.
|
130
|
-
|
131
|
-
The advantage of using method calls to transition from one state to anotehr is the method calls can be chained.
|
104
|
+
Given the above definition, we can transition from one state to another by calling `>>` with the newly desired state. This will raise a `LiteralEnums::TransitionError` if the transition is invalid.
|
132
105
|
|
133
106
|
```ruby
|
134
|
-
State::Pending
|
135
|
-
|
136
|
-
# valid to move to State::Approved from State::Pending.
|
107
|
+
State::Pending >> State::Approved # returns State::Approved.
|
108
|
+
State::Pending >> State::Published # raises a LiteralEnums::TransitionError.
|
137
109
|
```
|
138
110
|
|
139
111
|
## Installation
|
data/bench.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "literal_enums"
|
5
|
+
require "benchmark/ips"
|
6
|
+
|
7
|
+
class Color < Enum
|
8
|
+
Red("#f00")
|
9
|
+
Green("#0f0")
|
10
|
+
Blue("#00f")
|
11
|
+
end
|
12
|
+
|
13
|
+
Benchmark.ips do |x|
|
14
|
+
x.report("Cast") { Color.cast("f00") }
|
15
|
+
x.report("Lookup") { Color::Red }
|
16
|
+
x.report("Members") { Color.members }
|
17
|
+
x.report("Values") { Color.values }
|
18
|
+
end
|
data/lib/enum.rb
CHANGED
@@ -7,57 +7,94 @@ class Enum
|
|
7
7
|
alias_method :inspect, :name
|
8
8
|
|
9
9
|
def initialize(name, value)
|
10
|
+
@short_name = name.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase!
|
10
11
|
@name = "#{self.class.name}::#{name}"
|
11
|
-
@value = value
|
12
|
+
@value = value
|
12
13
|
end
|
13
14
|
|
14
15
|
class << self
|
16
|
+
attr_reader :members
|
17
|
+
|
18
|
+
def inherited(child)
|
19
|
+
TracePoint.new(:end) do |tp|
|
20
|
+
if tp.self == child
|
21
|
+
tp.self.freeze
|
22
|
+
tp.disable
|
23
|
+
end
|
24
|
+
end.enable
|
25
|
+
|
26
|
+
child.instance_eval do
|
27
|
+
@values = {}
|
28
|
+
@members = []
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def const_missing(name)
|
33
|
+
return super if frozen?
|
34
|
+
new(name)
|
35
|
+
end
|
36
|
+
|
15
37
|
def method_missing(name, *args, **kwargs, &block)
|
16
|
-
return super
|
38
|
+
return super if frozen?
|
39
|
+
return super unless name[0] =~ /[A-Z]/
|
17
40
|
new(name, *args, **kwargs, &block)
|
18
41
|
end
|
19
42
|
|
20
43
|
def cast(value)
|
21
|
-
|
44
|
+
@values[value]
|
22
45
|
end
|
23
46
|
|
24
47
|
def values
|
25
|
-
|
48
|
+
@values.keys
|
26
49
|
end
|
27
50
|
|
28
51
|
def each(&block)
|
29
|
-
members.each(&block)
|
30
|
-
end
|
31
|
-
|
32
|
-
def members
|
33
|
-
constants.map { |c| const_get(c) }.to_set
|
52
|
+
@members.each(&block)
|
34
53
|
end
|
35
54
|
|
36
55
|
private
|
37
56
|
|
38
|
-
def new(name,
|
39
|
-
|
40
|
-
|
57
|
+
def new(name, a = nil, b = nil, &block)
|
58
|
+
|
59
|
+
# If only one positional argument is provided and it's a proc, treat it as the transitions_to definition. Otherwise, the first argument is the value and the second argument is the transitions_to definition.
|
60
|
+
|
61
|
+
if !b && Proc === a
|
62
|
+
transitions_to = a
|
63
|
+
value = name
|
64
|
+
else
|
65
|
+
value = a || name
|
66
|
+
transitions_to = b
|
41
67
|
end
|
42
68
|
|
43
|
-
if
|
44
|
-
raise ArgumentError,
|
69
|
+
if self == Enum
|
70
|
+
raise ArgumentError,
|
71
|
+
"You can't add values to the abstract Enum class itself."
|
45
72
|
end
|
46
73
|
|
47
|
-
if
|
48
|
-
raise ArgumentError,
|
74
|
+
if const_defined?(name)
|
75
|
+
raise ArgumentError,
|
76
|
+
"Name conflict: '#{self.name}::#{name}' is already defined."
|
49
77
|
end
|
50
78
|
|
51
|
-
|
52
|
-
|
79
|
+
if @values[value]
|
80
|
+
raise ArgumentError,
|
81
|
+
"Value conflict: the value '#{value}' is defined for '#{self.cast(value).name}'."
|
82
|
+
end
|
53
83
|
|
54
84
|
class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
|
55
|
-
def #{name.to_s.
|
56
|
-
|
85
|
+
def #{name.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase!}?
|
86
|
+
@short_name == "#{name.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').downcase!}"
|
57
87
|
end
|
58
88
|
RUBY
|
59
89
|
|
60
|
-
|
90
|
+
member = super(name, value)
|
91
|
+
member.instance_eval(&block) if block_given?
|
92
|
+
member.define_singleton_method(:transitions_to, transitions_to) if transitions_to
|
93
|
+
member.freeze
|
94
|
+
|
95
|
+
const_set(name, member)
|
96
|
+
@members << member
|
97
|
+
@values[value] = member
|
61
98
|
end
|
62
99
|
end
|
63
100
|
end
|
@@ -1,32 +1,30 @@
|
|
1
1
|
module LiteralEnums
|
2
2
|
module Transitions
|
3
|
-
def
|
4
|
-
return
|
5
|
-
valid_next_states.any? { |m| m.name.to_s.demodulize.underscore.to_sym == name }
|
6
|
-
end
|
3
|
+
def >>(new_state)
|
4
|
+
return self if new_state == self
|
7
5
|
|
8
|
-
|
9
|
-
|
6
|
+
if transitions_to?(new_state)
|
7
|
+
new_state
|
8
|
+
else
|
9
|
+
raise TransitionError,
|
10
|
+
"You can't transition from #{self.name} to #{new_state.name}."
|
11
|
+
end
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
|
14
|
+
def transitions_to?(new_state)
|
15
|
+
possible_states = transitions_to
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
raise ArgumentError "You can only transition to another #{self.class.name}."
|
17
|
+
case possible_states
|
18
|
+
when Enum
|
19
|
+
possible_states == new_state
|
20
|
+
when Array
|
21
|
+
possible_states.include?(new_state)
|
21
22
|
end
|
22
|
-
|
23
|
-
valid_next_states.include?(new_state)
|
24
23
|
end
|
25
24
|
|
26
25
|
private
|
27
26
|
|
28
|
-
def
|
29
|
-
return Array(transitions_to) if respond_to? :transitions_to
|
27
|
+
def transitions_to
|
30
28
|
[]
|
31
29
|
end
|
32
30
|
end
|
data/lib/literal_enums.rb
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
require "active_support"
|
2
|
-
require "active_support/core_ext/string"
|
3
|
-
|
4
1
|
require "literal_enums/version"
|
5
2
|
require "literal_enums/transitions"
|
6
3
|
require "enum"
|
7
4
|
|
8
5
|
module LiteralEnums
|
9
|
-
|
10
|
-
|
6
|
+
Error = Module.new
|
7
|
+
StandardError = Class.new(StandardError) { include Error }
|
8
|
+
TransitionError = Class.new(StandardError) { include Error }
|
11
9
|
end
|
data/literal_enums.gemspec
CHANGED
@@ -17,6 +17,7 @@ Gem::Specification.new do |spec|
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
18
18
|
spec.metadata["source_code_uri"] = "https://github.com/joeldrapper/literal_enums"
|
19
19
|
spec.metadata["changelog_uri"] = "https://github.com/joeldrapper/literal_enums"
|
20
|
+
spec.metadata["funding_uri"] = "https://github.com/sponsors/joeldrapper"
|
20
21
|
|
21
22
|
# Specify which files should be added to the gem when it is released.
|
22
23
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
@@ -28,9 +29,5 @@ Gem::Specification.new do |spec|
|
|
28
29
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
29
30
|
spec.require_paths = ["lib"]
|
30
31
|
|
31
|
-
spec.
|
32
|
-
spec.add_development_dependency "rake", "~> 12.3.3"
|
33
|
-
spec.add_development_dependency "minitest", "~> 5.0"
|
34
|
-
|
35
|
-
spec.add_dependency "activesupport", ">= 7.0"
|
32
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
36
33
|
end
|
metadata
CHANGED
@@ -1,71 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: literal_enums
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Drapper
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
12
|
-
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: bundler
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - "~>"
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: 2.3.7
|
20
|
-
type: :development
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - "~>"
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: 2.3.7
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 12.3.3
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 12.3.3
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: minitest
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '5.0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '5.0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: activesupport
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '7.0'
|
62
|
-
type: :runtime
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '7.0'
|
11
|
+
date: 2022-12-14 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
69
13
|
description: A comprehensive Enum library for Ruby with literal-style syntax.
|
70
14
|
email:
|
71
15
|
- joel@drapper.me
|
@@ -73,15 +17,16 @@ executables: []
|
|
73
17
|
extensions: []
|
74
18
|
extra_rdoc_files: []
|
75
19
|
files:
|
76
|
-
- ".github/
|
20
|
+
- ".github/FUNDING.yml"
|
21
|
+
- ".github/workflows/ci.yml"
|
77
22
|
- ".gitignore"
|
78
23
|
- ".ruby-version"
|
79
24
|
- CODE_OF_CONDUCT.md
|
80
25
|
- Gemfile
|
81
|
-
- Gemfile.lock
|
82
26
|
- LICENSE.txt
|
83
27
|
- README.md
|
84
28
|
- Rakefile
|
29
|
+
- bench.rb
|
85
30
|
- bin/console
|
86
31
|
- bin/setup
|
87
32
|
- lib/enum.rb
|
@@ -96,6 +41,8 @@ metadata:
|
|
96
41
|
homepage_uri: https://github.com/joeldrapper/literal_enums
|
97
42
|
source_code_uri: https://github.com/joeldrapper/literal_enums
|
98
43
|
changelog_uri: https://github.com/joeldrapper/literal_enums
|
44
|
+
funding_uri: https://github.com/sponsors/joeldrapper
|
45
|
+
rubygems_mfa_required: 'true'
|
99
46
|
post_install_message:
|
100
47
|
rdoc_options: []
|
101
48
|
require_paths:
|
data/.github/workflows/ruby.yml
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
name: Ruby
|
2
|
-
|
3
|
-
on:
|
4
|
-
push:
|
5
|
-
branches: [ main ]
|
6
|
-
pull_request:
|
7
|
-
branches: [ main ]
|
8
|
-
|
9
|
-
jobs:
|
10
|
-
test:
|
11
|
-
runs-on: ubuntu-latest
|
12
|
-
strategy:
|
13
|
-
matrix:
|
14
|
-
ruby-version: ['2.7', '3.0']
|
15
|
-
|
16
|
-
steps:
|
17
|
-
- uses: actions/checkout@v2
|
18
|
-
- name: Set up Ruby
|
19
|
-
uses: ruby/setup-ruby@v1
|
20
|
-
with:
|
21
|
-
ruby-version: ${{ matrix.ruby-version }}
|
22
|
-
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
23
|
-
- name: Run tests
|
24
|
-
run: bundle exec rake
|
data/Gemfile.lock
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
literal_enums (1.1.0)
|
5
|
-
activesupport (~> 7.0.2.2)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activesupport (7.0.2.3)
|
11
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
12
|
-
i18n (>= 1.6, < 2)
|
13
|
-
minitest (>= 5.1)
|
14
|
-
tzinfo (~> 2.0)
|
15
|
-
concurrent-ruby (1.1.9)
|
16
|
-
i18n (1.10.0)
|
17
|
-
concurrent-ruby (~> 1.0)
|
18
|
-
minitest (5.15.0)
|
19
|
-
rake (12.3.3)
|
20
|
-
tzinfo (2.0.4)
|
21
|
-
concurrent-ruby (~> 1.0)
|
22
|
-
|
23
|
-
PLATFORMS
|
24
|
-
arm64-darwin-21
|
25
|
-
x86_64-linux
|
26
|
-
|
27
|
-
DEPENDENCIES
|
28
|
-
bundler (~> 2.3.7)
|
29
|
-
literal_enums!
|
30
|
-
minitest (~> 5.0)
|
31
|
-
rake (~> 12.3.3)
|
32
|
-
|
33
|
-
BUNDLED WITH
|
34
|
-
2.3.7
|