meta_enum 1.0.0 → 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/CHANGELOG.md +14 -0
- data/Gemfile.lock +1 -1
- data/README.md +18 -9
- data/lib/meta_enum/{value.rb → element.rb} +5 -6
- data/lib/meta_enum/{missing_value.rb → missing_element.rb} +6 -7
- data/lib/meta_enum/type.rb +58 -29
- data/lib/meta_enum/version.rb +1 -1
- data/lib/meta_enum.rb +2 -2
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae4f6d4921c00b29216e850aa59e679b34c3eba7d5cf9d5ae9365a69c81b75aa
|
4
|
+
data.tar.gz: fc7018df488e1de04230d58a9d5b8181ea9686157dd0dee48fa48e97c180b20f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdfd752d85a7df06677a109c44fb75589e2e494312a90860dc5b878cce6ab02de618154775c715251bf3e8bb3a5274d3e62d02cbdb71b7ed08f41247481998b1
|
7
|
+
data.tar.gz: a1ec0eb6670569f0bb5efa36b04c6406269b519d2313201c8c5d1fcc2be0eea641b714733f712392d05dd6e692d680f17e3aff37d243e91c3d8737321ad00cb4
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## 2.0.0 (January 27, 2018)
|
4
|
+
|
5
|
+
Support non-integer values.
|
6
|
+
|
7
|
+
This entailed some breaking changes:
|
8
|
+
|
9
|
+
* MetaEnum::Value renamed to MetaEnum::Element
|
10
|
+
* MetaEnum::MissingValue renamed to MetaEnum::MissingElement
|
11
|
+
* MetaEnum::Value#number renamed to value
|
12
|
+
* MetaEnum::Type#values renamed to elements
|
13
|
+
* MetaEnum::Type#values_by_name renamed to elements_by_name
|
14
|
+
* MetaEnum::Type#values_by_number renamed to elements_by_value
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# MetaEnum
|
2
2
|
|
3
3
|
MetaEnum is a library for handling enum types in Ruby. It makes it easy to
|
4
|
-
convert between external
|
4
|
+
convert between external values and internal names.
|
5
5
|
|
6
6
|
## Installation
|
7
7
|
|
@@ -32,16 +32,16 @@ ColorType = MetaEnum::Type.new(red: 0, green: 1, blue: 2)
|
|
32
32
|
Use the `[]` operator to lookup a value by name:
|
33
33
|
|
34
34
|
```ruby
|
35
|
-
ColorType[:green] # => #<MetaEnum::
|
35
|
+
ColorType[:green] # => #<MetaEnum::Element: 1 => green}>
|
36
36
|
```
|
37
37
|
|
38
38
|
Or lookup by number:
|
39
39
|
|
40
40
|
```ruby
|
41
|
-
ColorType[1] # => #<MetaEnum::
|
41
|
+
ColorType[1] # => #<MetaEnum::Element: 1 => green}>
|
42
42
|
```
|
43
43
|
|
44
|
-
|
44
|
+
Elements can also be easily compared with values or names:
|
45
45
|
|
46
46
|
```ruby
|
47
47
|
ColorType[:green] == 1 # => true
|
@@ -54,17 +54,17 @@ Missing names would almost always be a programming error, so that will raise an
|
|
54
54
|
ColorType[:purple] # => raises: KeyError: key not found: :purple
|
55
55
|
```
|
56
56
|
|
57
|
-
But missing
|
57
|
+
But missing values could mean that there are values defined externally we do not know about. So it is preferable not to raise an exception.
|
58
58
|
|
59
59
|
```ruby
|
60
|
-
ColorType[42] # => #<MetaEnum::
|
60
|
+
ColorType[42] # => #<MetaEnum::MissingElement: 42}>
|
61
61
|
```
|
62
62
|
|
63
|
-
|
63
|
+
Value and name can be retrieved from a `MetaEnum::Element`
|
64
64
|
|
65
65
|
```ruby
|
66
|
-
v = ColorType[:red] # => #<MetaEnum::
|
67
|
-
v.
|
66
|
+
v = ColorType[:red] # => #<MetaEnum::Element: 0 => red}>
|
67
|
+
v.value # => 0
|
68
68
|
v.name # => :red
|
69
69
|
```
|
70
70
|
|
@@ -75,6 +75,15 @@ AgeType = MetaEnum::Type.new(child: [0, "Less than 18"], adult: [1, "At least 18
|
|
75
75
|
AgeType[:child].data # => "Less than 18"
|
76
76
|
```
|
77
77
|
|
78
|
+
Non-integer values can be enabled by passing a value_normalizer to `MetaEnum::Type.new`. For example, to use string values:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
CardType = MetaEnum::Type.new({visa: "VS", mastercard: "MC", discover: "DS"}, value_normalizer: method(:String))
|
82
|
+
CardType[:visa] # => #<MetaEnum::Element: visa: "VS", data: nil>
|
83
|
+
CardType["VS"] # => #<MetaEnum::Element: visa: "VS", data: nil>
|
84
|
+
pry(main)> CardType["VS"].value # => "VS"
|
85
|
+
```
|
86
|
+
|
78
87
|
## Development
|
79
88
|
|
80
89
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module MetaEnum
|
2
|
-
class
|
3
|
-
attr_reader :
|
2
|
+
class Element
|
3
|
+
attr_reader :value, :name, :data, :type
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(value, name, data, type)
|
6
|
+
@value = value
|
7
7
|
@name = name.to_sym
|
8
8
|
@data = data
|
9
9
|
@type = type
|
@@ -18,11 +18,10 @@ module MetaEnum
|
|
18
18
|
false
|
19
19
|
end
|
20
20
|
|
21
|
-
def to_i; number; end
|
22
21
|
def to_s; name.to_s; end
|
23
22
|
|
24
23
|
def inspect
|
25
|
-
"#<#{self.class}: #{name}: #{
|
24
|
+
"#<#{self.class}: #{name}: #{value.inspect}, data: #{data.inspect}>"
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module MetaEnum
|
2
|
-
class
|
3
|
-
attr_reader :
|
2
|
+
class MissingElement
|
3
|
+
attr_reader :value, :type
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(value, type)
|
6
|
+
@value = value
|
7
7
|
@type = type
|
8
8
|
freeze
|
9
9
|
end
|
@@ -13,18 +13,17 @@ module MetaEnum
|
|
13
13
|
|
14
14
|
def ==(other)
|
15
15
|
other = type[other]
|
16
|
-
|
16
|
+
value == other.value && type == other.type
|
17
17
|
|
18
18
|
# type[] will raise for certain bad keys. Those are obviously not equal so return false.
|
19
19
|
rescue ArgumentError, KeyError
|
20
20
|
false
|
21
21
|
end
|
22
22
|
|
23
|
-
def to_i; number; end
|
24
23
|
def to_s; name.to_s; end
|
25
24
|
|
26
25
|
def inspect
|
27
|
-
"#<#{self.class}: #{
|
26
|
+
"#<#{self.class}: #{value.inspect}}>"
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
data/lib/meta_enum/type.rb
CHANGED
@@ -1,75 +1,104 @@
|
|
1
1
|
require 'set'
|
2
2
|
|
3
3
|
module MetaEnum
|
4
|
+
|
5
|
+
# ValueNormalizationError is raised on when a value normalization fails. It wraps the underlying exception.
|
6
|
+
class ValueNormalizationError < StandardError
|
7
|
+
attr_reader :original_exception, :original_value
|
8
|
+
|
9
|
+
def initialize(original_exception, original_value)
|
10
|
+
@original_exception = original_exception
|
11
|
+
@original_value = original_value
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
"original_exception: #{original_exception}, original_value: #{original_value}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
class Type
|
5
|
-
attr_reader :
|
20
|
+
attr_reader :elements, :elements_by_value, :elements_by_name
|
6
21
|
|
7
|
-
# Initialize takes a single hash of name to
|
22
|
+
# Initialize takes a single hash of name to value.
|
8
23
|
#
|
9
24
|
# e.g. MetaEnum::Type.new(red: 0, green: 1, blue: 2)
|
10
25
|
#
|
11
26
|
# Additional data can also be associated with each value by passing an array
|
12
|
-
# of [
|
27
|
+
# of [value, extra data]. This can be used for additional description or
|
13
28
|
# any other reason.
|
14
29
|
#
|
15
30
|
# e.g. MetaEnum::Type.new(small: [0, "Less than 10], large: [1, "At least 10"]
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
31
|
+
#
|
32
|
+
# value_normalizer is a callable object that normalizes values. The default
|
33
|
+
# converts all values to integers. To allow string values use method(:String).
|
34
|
+
def initialize(
|
35
|
+
elements,
|
36
|
+
value_normalizer: method(:Integer)
|
37
|
+
)
|
38
|
+
@value_normalizer = value_normalizer
|
39
|
+
@elements_by_value = {}
|
40
|
+
@elements_by_name = {}
|
41
|
+
@elements = Set.new
|
20
42
|
|
21
|
-
|
22
|
-
|
23
|
-
v =
|
24
|
-
raise ArgumentError, "duplicate
|
25
|
-
raise ArgumentError, "duplicate name: #{v.name}" if @
|
26
|
-
@
|
27
|
-
@
|
28
|
-
@
|
43
|
+
elements.each do |name, value_and_data|
|
44
|
+
value_and_data = Array(value_and_data)
|
45
|
+
v = Element.new normalize_value(value_and_data[0]), name, value_and_data[1], self
|
46
|
+
raise ArgumentError, "duplicate value: #{v.value}" if @elements_by_value.key? v.value
|
47
|
+
raise ArgumentError, "duplicate name: #{v.name}" if @elements_by_name.key? v.name
|
48
|
+
@elements_by_value[v.value] = v
|
49
|
+
@elements_by_name[v.name] = v
|
50
|
+
@elements.add(v)
|
29
51
|
end
|
30
52
|
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
53
|
+
@elements_by_value.freeze
|
54
|
+
@elements_by_name.freeze
|
55
|
+
@elements.freeze
|
34
56
|
freeze
|
35
57
|
end
|
36
58
|
|
37
|
-
# [] is a "do what I mean" operator. It returns the
|
59
|
+
# [] is a "do what I mean" operator. It returns the Element from this type depending on the key.
|
38
60
|
#
|
39
|
-
# When key is a symbol, it is considered the name of the
|
61
|
+
# When key is a symbol, it is considered the name of the Element to return.
|
40
62
|
# Since symbols are used from number, it is considered an error if the key is
|
41
63
|
# not found and it raises an exception.
|
42
64
|
#
|
43
65
|
# When key can be converted to an integer by Integer(), then it is
|
44
|
-
# considered the number of the
|
66
|
+
# considered the number of the Element to return. Retrieving by number is
|
45
67
|
# presumed to converting from external data where a missing value should not
|
46
|
-
# be considered fatal. In this case it returns a
|
68
|
+
# be considered fatal. In this case it returns a MissingElement is with number
|
47
69
|
# as the key. This allows a Type to only specify the values is needs while
|
48
70
|
# passing through the others unmodified.
|
49
71
|
#
|
50
|
-
# Finally, when key is a MetaEnum::
|
72
|
+
# Finally, when key is a MetaEnum::Element, it is simply returned (unless it
|
51
73
|
# belongs to a different Type in which case an ArgumentError is raised).
|
52
74
|
#
|
53
75
|
# See #values_by_number and #values_by_name for non-fuzzy value selection.
|
54
76
|
def [](key)
|
55
77
|
case key
|
56
|
-
when
|
78
|
+
when Element, MissingElement
|
57
79
|
raise ArgumentError, "wrong type" unless key.type == self
|
58
80
|
key
|
59
81
|
when Symbol
|
60
|
-
|
82
|
+
elements_by_name.fetch(key)
|
61
83
|
else
|
62
|
-
key =
|
63
|
-
|
84
|
+
key = normalize_value(key)
|
85
|
+
elements_by_value.fetch(key) { MissingElement.new key, self }
|
64
86
|
end
|
65
87
|
end
|
66
88
|
|
67
89
|
def inspect
|
68
|
-
sprintf('#<%s: {%s}>', self.class,
|
90
|
+
sprintf('#<%s: {%s}>', self.class, elements.to_a.map { |v| "#{v.name}: #{v.number}"}.join(", "))
|
69
91
|
end
|
70
92
|
|
71
93
|
def size
|
72
|
-
|
94
|
+
elements.size
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
def normalize_value(value)
|
99
|
+
@value_normalizer.call(value)
|
100
|
+
rescue StandardError => e
|
101
|
+
raise ValueNormalizationError.new(e, value)
|
73
102
|
end
|
74
103
|
end
|
75
104
|
end
|
data/lib/meta_enum/version.rb
CHANGED
data/lib/meta_enum.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: meta_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jack Christensen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-01-
|
11
|
+
date: 2018-01-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -75,6 +75,7 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
77
|
- ".travis.yml"
|
78
|
+
- CHANGELOG.md
|
78
79
|
- Gemfile
|
79
80
|
- Gemfile.lock
|
80
81
|
- LICENSE.txt
|
@@ -83,9 +84,9 @@ files:
|
|
83
84
|
- bin/console
|
84
85
|
- bin/setup
|
85
86
|
- lib/meta_enum.rb
|
86
|
-
- lib/meta_enum/
|
87
|
+
- lib/meta_enum/element.rb
|
88
|
+
- lib/meta_enum/missing_element.rb
|
87
89
|
- lib/meta_enum/type.rb
|
88
|
-
- lib/meta_enum/value.rb
|
89
90
|
- lib/meta_enum/version.rb
|
90
91
|
- meta_enum.gemspec
|
91
92
|
homepage: https://github.com/ccsalespro/meta_enum
|