meta_enum 1.0.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|