key_dial 1.1.0 → 1.2.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/lib/key_dial/coercion.rb +124 -124
- data/lib/key_dial/key_dialler.rb +1 -1
- data/lib/key_dial/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dda856c325133404a9948a0a97d98009d5a46fdcbb916977f4b280094ff2b08
|
4
|
+
data.tar.gz: 387b760bf24b91add075b1c4a9a05ae01fa8fa134695bad0caf718fcbacc7d1e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45e32b32d08741ef44825ee3749fd45c29949ef35c101e8c490e1d980c7af6aea3cec12e5c443a6fbeab133aa1a11518e110ca22d5235206e215b13634cc4fd2
|
7
|
+
data.tar.gz: 002c925e1c2558a58d19d0ab2123f47a5d150d8ce06da692404b39fd5120e151a1834a8deb0cd198ca0fae6a9c353cba1627388d9f81d8eb2c21f7eb492708d0
|
data/lib/key_dial/coercion.rb
CHANGED
@@ -2,13 +2,30 @@ module KeyDial
|
|
2
2
|
|
3
3
|
module Coercion
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
module Coercer
|
6
|
+
def to(type)
|
7
|
+
if type.is_a?(Class)
|
8
|
+
if type == self.class || self.class < type
|
9
|
+
return self
|
10
|
+
elsif (type == Hash || type < Hash) && type.respond_to?(:from)
|
11
|
+
return type.from(self)
|
12
|
+
elsif (type == Array || type < Array) && type.respond_to?(:from)
|
13
|
+
return type.from(self)
|
14
|
+
elsif (type == Struct || type < Struct) && type.respond_to?(:from)
|
15
|
+
return type.from(self)
|
16
|
+
else
|
17
|
+
raise ArgumentError, "Cannot coerce to " + type.to_s
|
18
|
+
end
|
19
|
+
else
|
20
|
+
raise ArgumentError, "Must specify a class to coerce to."
|
21
|
+
end
|
11
22
|
end
|
23
|
+
end
|
24
|
+
|
25
|
+
module Hashes
|
26
|
+
|
27
|
+
# Adds .to() method to instances of this class
|
28
|
+
include Coercer
|
12
29
|
|
13
30
|
def self.included(base)
|
14
31
|
base.extend ClassMethods
|
@@ -19,10 +36,30 @@ module KeyDial
|
|
19
36
|
# Allows you to do Hash.from(obj) to create a Hash from any object intelligently.
|
20
37
|
#
|
21
38
|
def from(obj)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
39
|
+
case obj
|
40
|
+
when Hash
|
41
|
+
return obj
|
42
|
+
when Array
|
43
|
+
# Hash from Array. Forgiving and avoids errors. ['a', 'b', 'c'] will become {0 => 'a', 1 => 'b', 2 => 'c'}
|
44
|
+
obj.each_with_index.map { |k, i|
|
45
|
+
if k.is_a?(Array)
|
46
|
+
if k.empty?
|
47
|
+
[i, nil]
|
48
|
+
elsif k.size == 2
|
49
|
+
k # k in this case is a keyval pair, e.g. [k, v]
|
50
|
+
else
|
51
|
+
[i, k]
|
52
|
+
end
|
53
|
+
else
|
54
|
+
[i, k]
|
55
|
+
end
|
56
|
+
}.to_h
|
57
|
+
when Struct
|
58
|
+
# Hash from Struct
|
59
|
+
return obj.to_h
|
60
|
+
else
|
61
|
+
{0 => obj}
|
62
|
+
end
|
26
63
|
end
|
27
64
|
|
28
65
|
end
|
@@ -31,31 +68,8 @@ module KeyDial
|
|
31
68
|
|
32
69
|
module Arrays
|
33
70
|
|
34
|
-
#
|
35
|
-
|
36
|
-
def to_hash
|
37
|
-
self.each_with_index.map { |k, i|
|
38
|
-
if k.is_a?(Array)
|
39
|
-
if k.empty?
|
40
|
-
[i, nil]
|
41
|
-
elsif k.size == 2
|
42
|
-
k # k in this case is a keyval pair, e.g. [k, v]
|
43
|
-
else
|
44
|
-
[i, k]
|
45
|
-
end
|
46
|
-
else
|
47
|
-
[i, k]
|
48
|
-
end
|
49
|
-
}.to_h
|
50
|
-
end
|
51
|
-
|
52
|
-
# Convert an Array to a Struct. ['a', 'b', 'c'] will become <Struct :'0'='a', :'1'='b', :'2'='c'>
|
53
|
-
#
|
54
|
-
# @param type_class If a sub-class of Struct is provided, this sub-class will be instantiated
|
55
|
-
#
|
56
|
-
def to_struct(type_class = nil)
|
57
|
-
return Coercion::Structs.create(self, type_class)
|
58
|
-
end
|
71
|
+
# Adds .to() method to instances of this class
|
72
|
+
include Coercer
|
59
73
|
|
60
74
|
def self.included(base)
|
61
75
|
base.extend ClassMethods
|
@@ -66,10 +80,18 @@ module KeyDial
|
|
66
80
|
# Allows you to do Array.from(obj) to create an Array from any object intelligently.
|
67
81
|
#
|
68
82
|
def from(obj)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
83
|
+
case obj
|
84
|
+
when Array
|
85
|
+
return obj
|
86
|
+
when Hash
|
87
|
+
# Array from Hash
|
88
|
+
return obj.to_a
|
89
|
+
when Struct
|
90
|
+
# Array from Struct
|
91
|
+
return obj.to_h.to_a
|
92
|
+
else
|
93
|
+
return [obj]
|
94
|
+
end
|
73
95
|
end
|
74
96
|
|
75
97
|
end
|
@@ -78,19 +100,10 @@ module KeyDial
|
|
78
100
|
|
79
101
|
module Structs
|
80
102
|
|
81
|
-
|
103
|
+
# Adds .to() method to instances of this class
|
104
|
+
include Coercer
|
82
105
|
|
83
|
-
|
84
|
-
#
|
85
|
-
# @param type_class If a sub-class of Struct is provided, the Struct will be converted to this sub-class
|
86
|
-
#
|
87
|
-
def to_struct(type_class = nil)
|
88
|
-
if type_class.is_a?(Class) && type_class < Struct
|
89
|
-
return Struct.from(self, type_class)
|
90
|
-
else
|
91
|
-
return self
|
92
|
-
end
|
93
|
-
end
|
106
|
+
EMPTY = Struct.new(:'0').new.freeze
|
94
107
|
|
95
108
|
def self.included(base)
|
96
109
|
base.extend ClassMethods
|
@@ -100,86 +113,73 @@ module KeyDial
|
|
100
113
|
|
101
114
|
# Allows you to do Struct.from(obj) to instantiate a Struct using keys/values from any object intelligently.
|
102
115
|
#
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
s
|
109
|
-
|
110
|
-
else
|
111
|
-
return Coercion::Structs.create(obj, type_class)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
# Struct creation function not really meant to be used directly. Prefer Struct.from(obj).
|
118
|
-
#
|
119
|
-
# @param from_obj Keys/values from this object will be used to fill out the new Struct.
|
120
|
-
# @param type_class If a sub-class of Struct is provided, this sub-class will be instantiated
|
121
|
-
#
|
122
|
-
def self.create(from_obj, type_class = nil)
|
123
|
-
if from_obj.is_a?(Hash) || from_obj.is_a?(Array) || from_obj.is_a?(Struct)
|
124
|
-
return EMPTY.dup if from_obj.empty? && type_class == nil
|
125
|
-
from = from_obj
|
126
|
-
else
|
127
|
-
from = [from_obj]
|
128
|
-
end
|
129
|
-
|
130
|
-
# Has a specific type of Struct been specified?
|
131
|
-
if type_class.is_a?(Class) && type_class < Struct
|
132
|
-
if from.is_a?(type_class)
|
133
|
-
# Has an instantiation of that type of Struct been passed in? If so, just return it
|
134
|
-
return from
|
135
|
-
else
|
136
|
-
values = []
|
137
|
-
if from.is_a?(Array)
|
138
|
-
# Get as many elements of array as this Struct can handle - discard the rest
|
139
|
-
values = from.first(type_class.members.size)
|
140
|
-
else
|
141
|
-
# Not an Array, so must be another Struct or Hash
|
142
|
-
type_class.members.each { |key|
|
143
|
-
if from.key?(key)
|
144
|
-
# If the object has this expected key, use it
|
145
|
-
values << from[key]
|
146
|
-
else
|
147
|
-
# Otherwise, fill this key with nil
|
148
|
-
values << nil
|
149
|
-
# Keys in the from object which don't match expected keys are discarded
|
150
|
-
end
|
151
|
-
}
|
152
|
-
end
|
153
|
-
# values now contains a value or nil for each of this class's expected keys
|
154
|
-
return type_class.new(*values)
|
116
|
+
def from(_obj)
|
117
|
+
from_obj = _obj
|
118
|
+
if !from_obj.is_a?(Struct) && !from_obj.is_a?(Hash) && !from_obj.is_a?(Array)
|
119
|
+
return EMPTY if _obj == EMPTY[0]
|
120
|
+
return EMPTY if _obj.nil?
|
121
|
+
# For non-keyed objects, we will treat the whole object like it's a value to push into the first property of a struct
|
122
|
+
from_obj = [_obj]
|
155
123
|
end
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
#
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
elsif k.respond_to?(:to_s) && !k.nil?
|
165
|
-
k.to_s.to_sym
|
124
|
+
|
125
|
+
struct_class = self
|
126
|
+
|
127
|
+
# Are we operating on a defined type of Struct?
|
128
|
+
if struct_class < Struct
|
129
|
+
if from_obj.is_a?(struct_class)
|
130
|
+
# Has an instantiation of that type of Struct been passed in? If so, just return it
|
131
|
+
return from_obj
|
166
132
|
else
|
167
|
-
#
|
168
|
-
|
169
|
-
|
133
|
+
# Get values
|
134
|
+
values = []
|
135
|
+
if from_obj.is_a?(Array)
|
136
|
+
# Get as many elements of array as this Struct can handle - discard the rest
|
137
|
+
values = from_obj.first(struct_class.members.size)
|
138
|
+
else
|
139
|
+
# Not an Array, so must be another Struct or Hash
|
140
|
+
struct_class.members.each { |key|
|
141
|
+
if from_obj.key?(key)
|
142
|
+
# If the object has this expected key, use it
|
143
|
+
values << from_obj[key]
|
144
|
+
else
|
145
|
+
# Otherwise, fill this key with nil
|
146
|
+
values << nil
|
147
|
+
# Keys in the from object which don't match expected keys are discarded
|
148
|
+
end
|
149
|
+
}
|
150
|
+
end
|
151
|
+
# values now contains a value or nil for each of this class's expected keys
|
152
|
+
return struct_class.new(*values)
|
170
153
|
end
|
171
|
-
}.reject(&:nil?)
|
172
|
-
if new_keys.size > 0
|
173
|
-
# Create anonymous Struct with the specified keys and values
|
174
|
-
return Struct.new(*new_keys).new(*new_values)
|
175
154
|
else
|
176
|
-
#
|
177
|
-
|
155
|
+
# Anonymous Struct
|
156
|
+
new_values = from_obj.is_a?(Array) ? from_obj : from_obj.values
|
157
|
+
# Iterate over the keys of the from object
|
158
|
+
# (Array.keys is monkeypatched in)
|
159
|
+
new_keys = from_obj.keys.each_with_index.map { |k, i|
|
160
|
+
if k.respond_to?(:to_sym) && k != ''
|
161
|
+
k.to_sym
|
162
|
+
elsif k.respond_to?(:to_s) && !k.nil?
|
163
|
+
k.to_s.to_sym
|
164
|
+
else
|
165
|
+
# If we can't construct a valid Struct key for this key, we discard the corresponding value
|
166
|
+
new_values.delete_at(i)
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
}.reject(&:nil?)
|
170
|
+
if new_keys.size > 0
|
171
|
+
# Create anonymous Struct with the specified keys and values
|
172
|
+
return Struct.new(*new_keys).new(*new_values)
|
173
|
+
else
|
174
|
+
# Return the Empty Struct
|
175
|
+
return EMPTY
|
176
|
+
end
|
178
177
|
end
|
178
|
+
|
179
|
+
rescue
|
180
|
+
return EMPTY
|
179
181
|
end
|
180
182
|
|
181
|
-
rescue
|
182
|
-
return EMPTY.dup
|
183
183
|
end
|
184
184
|
|
185
185
|
end
|
data/lib/key_dial/key_dialler.rb
CHANGED
@@ -380,7 +380,7 @@ module KeyDial
|
|
380
380
|
# Why would you do this?
|
381
381
|
deep_obj[key[:this][:value]] = Struct.from(deep_obj[key[:this][:value]])
|
382
382
|
elsif type_class.is_a?(Class) && type_class < Struct
|
383
|
-
deep_obj[key[:this][:value]] =
|
383
|
+
deep_obj[key[:this][:value]] = type_class.from(deep_obj[key[:this][:value]])
|
384
384
|
elsif type_class == String && deep_obj[key[:this][:value]].respond_to?(:to_s)
|
385
385
|
deep_obj[key[:this][:value]] = deep_obj[key[:this][:value]].to_s
|
386
386
|
elsif type_class == Symbol
|
data/lib/key_dial/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: key_dial
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Convincible
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-10-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|