structure 3.5.0 → 3.6.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/structure/builder.rb +2 -2
- data/lib/structure/types.rb +56 -5
- data/lib/structure/version.rb +1 -1
- data/lib/structure.rb +2 -2
- data/sig/structure/builder.rbs +1 -1
- data/sig/structure/types.rbs +4 -2
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f6aed363a91e514906a1c005fe2af6ec3583fa8742f997055def47e1f085c0c
|
4
|
+
data.tar.gz: 574b02c68a6a84f98384d9ba60c8b2d88b95c2cb3db49aa2eccb61e3e1dfc9ab
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a73835caa30f00145df491efd1bbcedbb2a7ada0cd0b2328cc8c0d9004bd51607328883630529165e9863a9852df40e17414854133a1d1d0144f690e49a50ef
|
7
|
+
data.tar.gz: ecb9bc59302300646d8dad3ea1345aecf236aec833e35cf1c83cedbfe5de5369c87965f3877d93e952cbf3536ff603fea2564032a07dba3db77c9872a4d46318
|
data/lib/structure/builder.rb
CHANGED
@@ -60,8 +60,8 @@ module Structure
|
|
60
60
|
@mappings.keys
|
61
61
|
end
|
62
62
|
|
63
|
-
def coercions
|
64
|
-
@types.transform_values { |type| Types.coerce(type) }
|
63
|
+
def coercions(context_class = nil)
|
64
|
+
@types.transform_values { |type| Types.coerce(type, context_class) }
|
65
65
|
end
|
66
66
|
|
67
67
|
def predicate_methods
|
data/lib/structure/types.rb
CHANGED
@@ -11,7 +11,7 @@ module Structure
|
|
11
11
|
|
12
12
|
# Main factory method for creating type coercers
|
13
13
|
#
|
14
|
-
# @param type [Class, Symbol, Array] Type specification
|
14
|
+
# @param type [Class, Symbol, Array, String] Type specification
|
15
15
|
# @return [Proc, Object] Coercion proc or the type itself if no coercion available
|
16
16
|
#
|
17
17
|
# @example Boolean type
|
@@ -25,15 +25,20 @@ module Structure
|
|
25
25
|
#
|
26
26
|
# @example Array types
|
27
27
|
# coerce([String]) # => proc that coerces array elements to String
|
28
|
-
|
28
|
+
#
|
29
|
+
# @example String class name (lazy resolved)
|
30
|
+
# coerce("MyClass") # => proc that resolves and coerces to MyClass
|
31
|
+
def coerce(type, context_class = nil)
|
29
32
|
case type
|
30
33
|
when :boolean
|
31
34
|
boolean
|
32
35
|
when :self
|
33
36
|
self_referential
|
37
|
+
when String
|
38
|
+
string_class(type, context_class)
|
34
39
|
when Array
|
35
40
|
if type.length == 1
|
36
|
-
array(type.first)
|
41
|
+
array(type.first, context_class)
|
37
42
|
else
|
38
43
|
type
|
39
44
|
end
|
@@ -48,6 +53,25 @@ module Structure
|
|
48
53
|
end
|
49
54
|
end
|
50
55
|
|
56
|
+
def resolve_class(class_name, context_class)
|
57
|
+
if context_class && defined?(context_class.name)
|
58
|
+
namespace = context_class.name.to_s.split("::")[0...-1]
|
59
|
+
if namespace.any?
|
60
|
+
begin
|
61
|
+
namespace.reduce(Object) { |mod, name| mod.const_get(name) }.const_get(class_name)
|
62
|
+
rescue NameError
|
63
|
+
Object.const_get(class_name)
|
64
|
+
end
|
65
|
+
else
|
66
|
+
Object.const_get(class_name)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
Object.const_get(class_name)
|
70
|
+
end
|
71
|
+
rescue NameError => e
|
72
|
+
raise NameError, "Unable to resolve class '#{class_name}': #{e.message}"
|
73
|
+
end
|
74
|
+
|
51
75
|
private
|
52
76
|
|
53
77
|
def boolean
|
@@ -66,7 +90,19 @@ module Structure
|
|
66
90
|
->(val) { type.parse(val) }
|
67
91
|
end
|
68
92
|
|
69
|
-
def
|
93
|
+
def string_class(class_name, context_class)
|
94
|
+
resolved_class = nil
|
95
|
+
proc do |value|
|
96
|
+
resolved_class ||= Structure::Types.resolve_class(class_name, context_class)
|
97
|
+
if resolved_class.respond_to?(:parse)
|
98
|
+
resolved_class.parse(value) # steep:ignore
|
99
|
+
else
|
100
|
+
value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def array(element_type, context_class = nil)
|
70
106
|
if element_type == :self
|
71
107
|
proc do |value|
|
72
108
|
unless value.respond_to?(:map)
|
@@ -75,8 +111,23 @@ module Structure
|
|
75
111
|
|
76
112
|
value.map { |element| parse(element) }
|
77
113
|
end
|
114
|
+
elsif element_type.is_a?(String)
|
115
|
+
proc do |value|
|
116
|
+
unless value.respond_to?(:map)
|
117
|
+
raise TypeError, "can't convert #{value.class} into Array"
|
118
|
+
end
|
119
|
+
|
120
|
+
resolved_class = Structure::Types.resolve_class(element_type, context_class)
|
121
|
+
value.map do |element|
|
122
|
+
if resolved_class.respond_to?(:parse)
|
123
|
+
resolved_class.parse(element)
|
124
|
+
else
|
125
|
+
element
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
78
129
|
else
|
79
|
-
element_coercer = coerce(element_type)
|
130
|
+
element_coercer = coerce(element_type, context_class)
|
80
131
|
lambda do |value|
|
81
132
|
unless value.respond_to?(:map)
|
82
133
|
raise TypeError, "can't convert #{value.class} into Array"
|
data/lib/structure/version.rb
CHANGED
data/lib/structure.rb
CHANGED
@@ -37,13 +37,13 @@ module Structure
|
|
37
37
|
|
38
38
|
# capture locals for method generation
|
39
39
|
mappings = builder.mappings
|
40
|
-
coercions = builder.coercions
|
40
|
+
coercions = builder.coercions(klass)
|
41
41
|
predicates = builder.predicate_methods
|
42
42
|
after = builder.after_parse_callback
|
43
43
|
|
44
44
|
# Define predicate methods
|
45
45
|
predicates.each do |pred, attr|
|
46
|
-
klass.define_method(pred) { public_send(attr) }
|
46
|
+
klass.define_method(pred) { !!public_send(attr) }
|
47
47
|
end
|
48
48
|
|
49
49
|
# recursive to_h
|
data/sig/structure/builder.rbs
CHANGED
@@ -14,7 +14,7 @@ module Structure
|
|
14
14
|
def mappings: () -> Hash[Symbol, String]
|
15
15
|
def types: () -> Hash[Symbol, untyped]
|
16
16
|
def defaults: () -> Hash[Symbol, untyped]
|
17
|
-
def coercions: () -> Hash[Symbol, Proc]
|
17
|
+
def coercions: (?untyped? context_class) -> Hash[Symbol, Proc]
|
18
18
|
def predicate_methods: () -> Hash[Symbol, Symbol]
|
19
19
|
def after_parse_callback: () -> (Proc | nil)
|
20
20
|
end
|
data/sig/structure/types.rbs
CHANGED
@@ -4,11 +4,13 @@ module Structure
|
|
4
4
|
|
5
5
|
self.@boolean: Proc
|
6
6
|
|
7
|
-
def self.coerce: (untyped type) -> untyped
|
7
|
+
def self.coerce: (untyped type, ?untyped? context_class) -> untyped
|
8
|
+
def self.resolve_class: (String class_name, untyped? context_class) -> untyped
|
8
9
|
|
9
10
|
private def self.boolean: () -> Proc
|
10
11
|
private def self.self_referential: () -> Proc
|
11
|
-
private def self.
|
12
|
+
private def self.string_class: (String class_name, untyped? context_class) -> Proc
|
13
|
+
private def self.array: (untyped element_type, ?untyped? context_class) -> Proc
|
12
14
|
private def self.parseable: (untyped type) -> Proc
|
13
15
|
private def self.kernel: (Class type) -> Proc
|
14
16
|
private def self.parse: (untyped val) -> untyped
|