nrser 0.0.19 → 0.0.20
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/nrser/hash.rb +41 -4
- data/lib/nrser/meta/props/prop.rb +212 -0
- data/lib/nrser/meta/props.rb +123 -218
- data/lib/nrser/refinements/hash.rb +16 -1
- data/lib/nrser/refinements/string.rb +8 -0
- data/lib/nrser/string.rb +50 -0
- data/lib/nrser/types/hash.rb +1 -1
- data/lib/nrser/version.rb +1 -1
- data/spec/nrser/meta/props_spec.rb +7 -7
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01fe1d56c4df90623c6407128463f67ca2e65426
|
4
|
+
data.tar.gz: 0b1dfcb6cdd036647526482901cffe7e652cf189
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af6cf0974b665d43b2b56a5fecbc1c44c2014f2aeb031eb3b831d599d55003a5d83ba6a6cdf604b34fc64700a6f713a96c8d9b69e51f550a3008449ee2d5de79
|
7
|
+
data.tar.gz: e368146e2161490ed4a831063e6a79540e084c45c52a685801776b759c43cf37e5d679bad11bbe2b22fd8f2d78012276f73843a0afa0a14d54226bccd138b8ca
|
data/lib/nrser/hash.rb
CHANGED
@@ -238,22 +238,59 @@ module NRSER
|
|
238
238
|
# @see http://www.rubydoc.info/gems/activesupport/5.1.3/Hash:symbolize_keys!
|
239
239
|
#
|
240
240
|
# @param [Hash] hash
|
241
|
-
# Hash to mutate.
|
242
241
|
#
|
243
|
-
# @return [
|
244
|
-
# @todo Document return value.
|
242
|
+
# @return [Hash]
|
245
243
|
#
|
246
244
|
def self.symbolize_keys! hash
|
247
245
|
transform_keys!(hash) { |key| key.to_sym rescue key }
|
248
246
|
end # .symbolize_keys!
|
249
247
|
|
250
248
|
|
251
|
-
|
249
|
+
# Returns a new hash with all keys that respond to `#to_sym` converted to
|
250
|
+
# symbols.
|
251
|
+
#
|
252
|
+
# Lifted from ActiveSupport.
|
253
|
+
#
|
254
|
+
# @see http://www.rubydoc.info/gems/activesupport/5.1.3/Hash:symbolize_keys
|
255
|
+
#
|
256
|
+
# @param [Hash] hash
|
257
|
+
#
|
258
|
+
# @return [Hash]
|
259
|
+
#
|
252
260
|
def self.symbolize_keys hash
|
253
261
|
# File 'lib/active_support/core_ext/hash/keys.rb', line 54
|
254
262
|
transform_keys(hash) { |key| key.to_sym rescue key }
|
255
263
|
end
|
256
264
|
|
265
|
+
|
266
|
+
# Converts all keys into strings by calling `#to_s` on them. **Mutates the
|
267
|
+
# hash.**
|
268
|
+
#
|
269
|
+
# Lifted from ActiveSupport.
|
270
|
+
#
|
271
|
+
# @param [Hash] hash
|
272
|
+
#
|
273
|
+
# @return [Hash<String, *>]
|
274
|
+
#
|
275
|
+
def self.stringify_keys! hash
|
276
|
+
transform_keys! hash, &:to_s
|
277
|
+
end
|
278
|
+
|
279
|
+
|
280
|
+
# Returns a new hash with all keys transformed to strings by calling `#to_s`
|
281
|
+
# on them.
|
282
|
+
#
|
283
|
+
# Lifted from ActiveSupport.
|
284
|
+
#
|
285
|
+
# @param [Hash] hash
|
286
|
+
#
|
287
|
+
# @return [Hash<String, *>]
|
288
|
+
#
|
289
|
+
def self.stringify_keys hash
|
290
|
+
transform_keys hash, &:to_s
|
291
|
+
end
|
292
|
+
|
293
|
+
|
257
294
|
# Lifted from ActiveSupport.
|
258
295
|
#
|
259
296
|
# @see http://www.rubydoc.info/gems/activesupport/5.1.3/Hash:slice
|
@@ -0,0 +1,212 @@
|
|
1
|
+
require 'nrser/no_arg'
|
2
|
+
|
3
|
+
require 'nrser/refinements'
|
4
|
+
require 'nrser/refinements/types'
|
5
|
+
|
6
|
+
using NRSER::Types
|
7
|
+
|
8
|
+
module NRSER
|
9
|
+
module Meta
|
10
|
+
module Props
|
11
|
+
|
12
|
+
class Prop
|
13
|
+
attr_accessor :defined_in,
|
14
|
+
:name,
|
15
|
+
:type,
|
16
|
+
:source
|
17
|
+
|
18
|
+
|
19
|
+
def initialize defined_in,
|
20
|
+
name,
|
21
|
+
type: t.any,
|
22
|
+
default: NRSER::NO_ARG,
|
23
|
+
source: nil
|
24
|
+
|
25
|
+
@defined_in = defined_in
|
26
|
+
@name = name
|
27
|
+
@type = t.make type
|
28
|
+
@source = source
|
29
|
+
@default = default
|
30
|
+
|
31
|
+
if @source.nil?
|
32
|
+
@instance_variable_source = false
|
33
|
+
else
|
34
|
+
source_str = source.to_s
|
35
|
+
@instance_variable_source = source_str[0] == '@'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
# @todo Document default? method.
|
41
|
+
#
|
42
|
+
# @param [type] arg_name
|
43
|
+
# @todo Add name param description.
|
44
|
+
#
|
45
|
+
# @return [return_type]
|
46
|
+
# @todo Document return value.
|
47
|
+
#
|
48
|
+
def default?
|
49
|
+
@default != NRSER::NO_ARG
|
50
|
+
end # #default?
|
51
|
+
|
52
|
+
|
53
|
+
def default
|
54
|
+
if default?
|
55
|
+
@default
|
56
|
+
else
|
57
|
+
raise NameError.new NRSER.squish <<-END
|
58
|
+
Prop #{ self } has no default value.
|
59
|
+
END
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# @todo Document source? method.
|
65
|
+
#
|
66
|
+
# @param [type] arg_name
|
67
|
+
# @todo Add name param description.
|
68
|
+
#
|
69
|
+
# @return [return_type]
|
70
|
+
# @todo Document return value.
|
71
|
+
#
|
72
|
+
def source?
|
73
|
+
!@source.nil?
|
74
|
+
end # #source?
|
75
|
+
|
76
|
+
|
77
|
+
# @todo Document instance_variable_source? method.
|
78
|
+
#
|
79
|
+
# @param [type] arg_name
|
80
|
+
# @todo Add name param description.
|
81
|
+
#
|
82
|
+
# @return [return_type]
|
83
|
+
# @todo Document return value.
|
84
|
+
#
|
85
|
+
def instance_variable_source?
|
86
|
+
@instance_variable_source
|
87
|
+
end # #instance_variable_source?
|
88
|
+
|
89
|
+
|
90
|
+
# @todo Document primary? method.
|
91
|
+
#
|
92
|
+
# @param [type] arg_name
|
93
|
+
# @todo Add name param description.
|
94
|
+
#
|
95
|
+
# @return [return_type]
|
96
|
+
# @todo Document return value.
|
97
|
+
#
|
98
|
+
def primary?
|
99
|
+
!source?
|
100
|
+
end # #primary?
|
101
|
+
|
102
|
+
|
103
|
+
# @todo Document get method.
|
104
|
+
#
|
105
|
+
# @param [type] arg_name
|
106
|
+
# @todo Add name param description.
|
107
|
+
#
|
108
|
+
# @return [return_type]
|
109
|
+
# @todo Document return value.
|
110
|
+
#
|
111
|
+
def get instance
|
112
|
+
if source?
|
113
|
+
if instance_variable_source?
|
114
|
+
instance.instance_variable_get source
|
115
|
+
else
|
116
|
+
instance.send source
|
117
|
+
end
|
118
|
+
else
|
119
|
+
values(instance)[name]
|
120
|
+
end
|
121
|
+
end # #get
|
122
|
+
|
123
|
+
|
124
|
+
# @todo Document set method.
|
125
|
+
#
|
126
|
+
# @param [type] arg_name
|
127
|
+
# @todo Add name param description.
|
128
|
+
#
|
129
|
+
# @return [return_type]
|
130
|
+
# @todo Document return value.
|
131
|
+
#
|
132
|
+
def set instance, value
|
133
|
+
unless type.test value
|
134
|
+
raise TypeError.new NRSER.squish <<-END
|
135
|
+
#{ defined_in }##{ name } must be of type #{ type };
|
136
|
+
found #{ value.inspect }
|
137
|
+
END
|
138
|
+
end
|
139
|
+
|
140
|
+
values(instance)[name] = value
|
141
|
+
end # #set
|
142
|
+
|
143
|
+
|
144
|
+
|
145
|
+
# @todo Document set_from_hash method.
|
146
|
+
#
|
147
|
+
# @param [type] arg_name
|
148
|
+
# @todo Add name param description.
|
149
|
+
#
|
150
|
+
# @return [return_type]
|
151
|
+
# @todo Document return value.
|
152
|
+
#
|
153
|
+
def set_from_values_hash instance, **values
|
154
|
+
if values.key? name
|
155
|
+
set instance, values[name]
|
156
|
+
else
|
157
|
+
if default?
|
158
|
+
set instance, default.dup
|
159
|
+
else
|
160
|
+
raise TypeError.new NRSER.squish <<-END
|
161
|
+
Prop #{ name } has no default value and no value was provided in
|
162
|
+
values #{ values.inspect }.
|
163
|
+
END
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end # #set_from_hash
|
167
|
+
|
168
|
+
|
169
|
+
|
170
|
+
# @todo Document to_data method.
|
171
|
+
#
|
172
|
+
# @param [type] arg_name
|
173
|
+
# @todo Add name param description.
|
174
|
+
#
|
175
|
+
# @return [return_type]
|
176
|
+
# @todo Document return value.
|
177
|
+
#
|
178
|
+
def to_data instance
|
179
|
+
value = get instance
|
180
|
+
|
181
|
+
if value.respond_to? :to_data
|
182
|
+
value.to_data
|
183
|
+
else
|
184
|
+
value
|
185
|
+
end
|
186
|
+
end # #to_data
|
187
|
+
|
188
|
+
|
189
|
+
|
190
|
+
private
|
191
|
+
|
192
|
+
# @todo Document values method.
|
193
|
+
#
|
194
|
+
# @param [type] arg_name
|
195
|
+
# @todo Add name param description.
|
196
|
+
#
|
197
|
+
# @return [return_type]
|
198
|
+
# @todo Document return value.
|
199
|
+
#
|
200
|
+
def values instance
|
201
|
+
unless instance.instance_variable_defined? PROP_VALUES_VARIABLE_NAME
|
202
|
+
instance.instance_variable_set PROP_VALUES_VARIABLE_NAME, {}
|
203
|
+
end
|
204
|
+
|
205
|
+
instance.instance_variable_get PROP_VALUES_VARIABLE_NAME
|
206
|
+
end # #value
|
207
|
+
|
208
|
+
end # class Prop
|
209
|
+
|
210
|
+
end # module Props
|
211
|
+
end # module Meta
|
212
|
+
end # module NRSER
|
data/lib/nrser/meta/props.rb
CHANGED
@@ -1,189 +1,28 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'pp'
|
2
|
+
|
3
|
+
require 'nrser/refinements'
|
4
|
+
require 'nrser/refinements/types'
|
3
5
|
|
4
|
-
|
6
|
+
using NRSER
|
7
|
+
using NRSER::Types
|
8
|
+
|
9
|
+
module NRSER
|
10
|
+
module Meta
|
5
11
|
|
6
|
-
#
|
7
12
|
module Props
|
13
|
+
CLASS_KEY = '__class__';
|
8
14
|
PROPS_VARIABLE_NAME = :@__NRSER_props
|
9
15
|
PROP_VALUES_VARIABLE_NAME = :@__NRSER_prop_values
|
10
16
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
type: T.any,
|
21
|
-
default: NRSER::NO_ARG,
|
22
|
-
source: nil
|
23
|
-
|
24
|
-
@defined_in = defined_in
|
25
|
-
@name = name
|
26
|
-
@type = NRSER::Types.make type
|
27
|
-
@source = source
|
28
|
-
@default = default
|
29
|
-
|
30
|
-
if @source.nil?
|
31
|
-
@instance_variable_source = false
|
32
|
-
else
|
33
|
-
source_str = source.to_s
|
34
|
-
@instance_variable_source = source_str[0] == '@'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
|
39
|
-
# @todo Document default? method.
|
40
|
-
#
|
41
|
-
# @param [type] arg_name
|
42
|
-
# @todo Add name param description.
|
43
|
-
#
|
44
|
-
# @return [return_type]
|
45
|
-
# @todo Document return value.
|
46
|
-
#
|
47
|
-
def default?
|
48
|
-
@default != NRSER::NO_ARG
|
49
|
-
end # #default?
|
50
|
-
|
51
|
-
|
52
|
-
def default
|
53
|
-
if default?
|
54
|
-
@default
|
55
|
-
else
|
56
|
-
raise NameError.new NRSER.squish <<-END
|
57
|
-
Prop #{ self } has no default value.
|
58
|
-
END
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
# @todo Document source? method.
|
64
|
-
#
|
65
|
-
# @param [type] arg_name
|
66
|
-
# @todo Add name param description.
|
67
|
-
#
|
68
|
-
# @return [return_type]
|
69
|
-
# @todo Document return value.
|
70
|
-
#
|
71
|
-
def source?
|
72
|
-
!@source.nil?
|
73
|
-
end # #source?
|
74
|
-
|
75
|
-
|
76
|
-
# @todo Document instance_variable_source? method.
|
77
|
-
#
|
78
|
-
# @param [type] arg_name
|
79
|
-
# @todo Add name param description.
|
80
|
-
#
|
81
|
-
# @return [return_type]
|
82
|
-
# @todo Document return value.
|
83
|
-
#
|
84
|
-
def instance_variable_source?
|
85
|
-
@instance_variable_source
|
86
|
-
end # #instance_variable_source?
|
87
|
-
|
88
|
-
|
89
|
-
# @todo Document primary? method.
|
90
|
-
#
|
91
|
-
# @param [type] arg_name
|
92
|
-
# @todo Add name param description.
|
93
|
-
#
|
94
|
-
# @return [return_type]
|
95
|
-
# @todo Document return value.
|
96
|
-
#
|
97
|
-
def primary?
|
98
|
-
!source?
|
99
|
-
end # #primary?
|
100
|
-
|
101
|
-
|
102
|
-
# @todo Document get method.
|
103
|
-
#
|
104
|
-
# @param [type] arg_name
|
105
|
-
# @todo Add name param description.
|
106
|
-
#
|
107
|
-
# @return [return_type]
|
108
|
-
# @todo Document return value.
|
109
|
-
#
|
110
|
-
def get instance
|
111
|
-
if source?
|
112
|
-
if instance_variable_source?
|
113
|
-
instance.instance_variable_get source
|
114
|
-
else
|
115
|
-
instance.send source
|
116
|
-
end
|
117
|
-
else
|
118
|
-
values(instance)[name]
|
119
|
-
end
|
120
|
-
end # #get
|
121
|
-
|
122
|
-
|
123
|
-
# @todo Document set method.
|
124
|
-
#
|
125
|
-
# @param [type] arg_name
|
126
|
-
# @todo Add name param description.
|
127
|
-
#
|
128
|
-
# @return [return_type]
|
129
|
-
# @todo Document return value.
|
130
|
-
#
|
131
|
-
def set instance, value
|
132
|
-
unless type.test value
|
133
|
-
raise TypeError.new NRSER.squish <<-END
|
134
|
-
#{ defined_in }##{ name } must be of type #{ type };
|
135
|
-
found #{ value.inspect }
|
136
|
-
END
|
137
|
-
end
|
138
|
-
|
139
|
-
values(instance)[name] = value
|
140
|
-
end # #set
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
# @todo Document set_from_hash method.
|
145
|
-
#
|
146
|
-
# @param [type] arg_name
|
147
|
-
# @todo Add name param description.
|
148
|
-
#
|
149
|
-
# @return [return_type]
|
150
|
-
# @todo Document return value.
|
151
|
-
#
|
152
|
-
def set_from_values_hash instance, **values
|
153
|
-
if values.key? name
|
154
|
-
set instance, values[name]
|
155
|
-
else
|
156
|
-
if default?
|
157
|
-
set instance, default.dup
|
158
|
-
else
|
159
|
-
raise TypeError.new NRSER.squish <<-END
|
160
|
-
Prop #{ name } has no default value and no value was provided in
|
161
|
-
values #{ values.inspect }.
|
162
|
-
END
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end # #set_from_hash
|
166
|
-
|
167
|
-
|
168
|
-
private
|
169
|
-
|
170
|
-
# @todo Document values method.
|
171
|
-
#
|
172
|
-
# @param [type] arg_name
|
173
|
-
# @todo Add name param description.
|
174
|
-
#
|
175
|
-
# @return [return_type]
|
176
|
-
# @todo Document return value.
|
177
|
-
#
|
178
|
-
def values instance
|
179
|
-
unless instance.instance_variable_defined? PROP_VALUES_VARIABLE_NAME
|
180
|
-
instance.instance_variable_set PROP_VALUES_VARIABLE_NAME, {}
|
181
|
-
end
|
182
|
-
|
183
|
-
instance.instance_variable_get PROP_VALUES_VARIABLE_NAME
|
184
|
-
end # #value
|
185
|
-
|
186
|
-
end # class Prop
|
17
|
+
|
18
|
+
# Module Methods (Utilities)
|
19
|
+
# =====================================================================
|
20
|
+
#
|
21
|
+
# These are *NOT* mixed in to including classes, and must be accessed
|
22
|
+
# via `NRSER::Meta::Props.<method_name>`.
|
23
|
+
#
|
24
|
+
# They're utilities that should only really need to be used internally.
|
25
|
+
#
|
187
26
|
|
188
27
|
|
189
28
|
# @todo Document get_props_ref method.
|
@@ -203,8 +42,50 @@ module Props
|
|
203
42
|
end # .get_props_ref
|
204
43
|
|
205
44
|
|
206
|
-
|
45
|
+
# Instantiate a class from a data hash. The hash must contain the
|
46
|
+
# `__class__` key and the target class must be loaded already.
|
47
|
+
#
|
48
|
+
# **WARNING**
|
49
|
+
#
|
50
|
+
# I'm sure this is all-sorts of unsafe. Please don't ever think this is
|
51
|
+
# reasonable to use on untrusted data.
|
52
|
+
#
|
53
|
+
# @param [Hash<String, Object>] data
|
54
|
+
#
|
55
|
+
# @return [Object]
|
56
|
+
# @todo Document return value.
|
57
|
+
#
|
58
|
+
#
|
59
|
+
#
|
60
|
+
def self.from_data data
|
61
|
+
t.hash_.check data
|
207
62
|
|
63
|
+
unless data.key?(CLASS_KEY)
|
64
|
+
raise ArgumentError.new <<-END.dedent
|
65
|
+
Data is missing #{ CLASS_KEY } key - no idea what class to instantiate.
|
66
|
+
|
67
|
+
#{ data.pretty_inspect }
|
68
|
+
END
|
69
|
+
end
|
70
|
+
|
71
|
+
class_name = t.str.check data[CLASS_KEY]
|
72
|
+
klass = class_name.to_const
|
73
|
+
klass.from_data data
|
74
|
+
end # .from_data
|
75
|
+
|
76
|
+
|
77
|
+
# Hook to extend the including class with {NRSER::Meta::Props:ClassMethods}
|
78
|
+
def self.included base
|
79
|
+
base.extend ClassMethods
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
# Mixed-In Class Methods
|
84
|
+
# =====================================================================
|
85
|
+
|
86
|
+
# Methods added to the including *class* via `extend`.
|
87
|
+
#
|
88
|
+
module ClassMethods
|
208
89
|
|
209
90
|
# @todo Document props method.
|
210
91
|
#
|
@@ -214,16 +95,16 @@ module Props
|
|
214
95
|
# @return [return_type]
|
215
96
|
# @todo Document return value.
|
216
97
|
#
|
217
|
-
def props
|
218
|
-
result = if !
|
219
|
-
superclass.props
|
98
|
+
def props only_own: false, only_primary: false
|
99
|
+
result = if !only_own && superclass.respond_to?(:props)
|
100
|
+
superclass.props only_own: only_own, only_primary: only_primary
|
220
101
|
else
|
221
102
|
{}
|
222
103
|
end
|
223
104
|
|
224
105
|
own_props = NRSER::Meta::Props.get_props_ref self
|
225
106
|
|
226
|
-
if
|
107
|
+
if only_primary
|
227
108
|
own_props.each {|name, prop|
|
228
109
|
if prop.primary?
|
229
110
|
result[name] = prop
|
@@ -248,7 +129,7 @@ module Props
|
|
248
129
|
def prop name, **opts
|
249
130
|
ref = NRSER::Meta::Props.get_props_ref self
|
250
131
|
|
251
|
-
|
132
|
+
t.sym.check name
|
252
133
|
|
253
134
|
if ref.key? name
|
254
135
|
raise ArgumentError.new NRSER.squish <<-END
|
@@ -275,38 +156,27 @@ module Props
|
|
275
156
|
end # #prop
|
276
157
|
|
277
158
|
|
278
|
-
|
279
|
-
# @todo Document from_h method.
|
159
|
+
# Instantiate from a data hash.
|
280
160
|
#
|
281
|
-
# @
|
282
|
-
#
|
161
|
+
# @todo
|
162
|
+
# This needs to be extended to handle prop'd classes nested in
|
163
|
+
# arrays and hashes... but for the moment, it is what it is.
|
283
164
|
#
|
284
|
-
# @
|
285
|
-
# @todo Document return value.
|
165
|
+
# @param [Hash<String, Object>] data
|
286
166
|
#
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
)
|
294
|
-
end # #from_h
|
167
|
+
# @return [self]
|
168
|
+
#
|
169
|
+
def from_data data
|
170
|
+
self.new data.symbolize_keys
|
171
|
+
end # #from_data
|
172
|
+
|
295
173
|
|
296
|
-
|
297
174
|
end # module ClassMethods
|
298
175
|
|
299
176
|
|
300
|
-
#
|
301
|
-
def self.included base
|
302
|
-
base.extend ClassMethods
|
303
|
-
end
|
304
|
-
|
305
|
-
|
306
|
-
# Instance Methods
|
177
|
+
# Mixed-In Instance Methods
|
307
178
|
# =====================================================================
|
308
179
|
|
309
|
-
|
310
180
|
# @todo Document initialize_props method.
|
311
181
|
#
|
312
182
|
# @param [type] arg_name
|
@@ -316,26 +186,60 @@ module Props
|
|
316
186
|
# @todo Document return value.
|
317
187
|
#
|
318
188
|
def initialize_props values
|
319
|
-
self.class.props(
|
189
|
+
self.class.props(only_primary: true).each { |name, prop|
|
320
190
|
prop.set_from_values_hash self, values
|
321
191
|
}
|
322
192
|
end # #initialize_props
|
323
193
|
|
324
194
|
|
195
|
+
def merge overrides = {}
|
196
|
+
self.class.new(
|
197
|
+
self.to_h(only_primary: true).merge(overrides.symbolize_keys)
|
198
|
+
)
|
199
|
+
end
|
200
|
+
|
201
|
+
|
325
202
|
# @todo Document to_h method.
|
326
203
|
#
|
327
204
|
# @param [type] arg_name
|
328
205
|
# @todo Add name param description.
|
329
206
|
#
|
330
|
-
# @return [
|
207
|
+
# @return [Hash<Symbol, Object>]
|
331
208
|
# @todo Document return value.
|
332
209
|
#
|
333
|
-
def to_h
|
334
|
-
|
335
|
-
|
336
|
-
) { |name, prop| prop.get self }
|
210
|
+
def to_h only_own: false, only_primary: false
|
211
|
+
self.class.props(only_own: only_own, only_primary: only_primary).
|
212
|
+
map_values { |name, prop| prop.get self }
|
337
213
|
end # #to_h
|
338
214
|
|
215
|
+
# Create a "data" representation suitable for transport, storage, etc.
|
216
|
+
#
|
217
|
+
# The result is meant to consist of only basic data types and structures -
|
218
|
+
# strings, numbers, arrays, hashes, datetimes, etc... though it depends on
|
219
|
+
# any custom objects it encounters correctly responding to `#to_data` for
|
220
|
+
# this to happen (as is implemented from classes that mix in Props here).
|
221
|
+
#
|
222
|
+
# Prop names are converted to strings (from symbols) since though YAML
|
223
|
+
# supports symbol values, they have poor portability across languages,
|
224
|
+
# and they mean the same thing in this situation.
|
225
|
+
#
|
226
|
+
# @param [type] arg_name
|
227
|
+
# @todo Add name param description.
|
228
|
+
#
|
229
|
+
# @return [Hash<String, Object>]
|
230
|
+
# @todo Document return value.
|
231
|
+
#
|
232
|
+
def to_data only_own: false, only_primary: false, add_class: true
|
233
|
+
self.class.props(only_own: false, only_primary: false).
|
234
|
+
map { |name, prop|
|
235
|
+
[name.to_s, prop.to_data(self)]
|
236
|
+
}.
|
237
|
+
to_h.
|
238
|
+
tap { |hash|
|
239
|
+
hash[CLASS_KEY] = self.class.name if add_class
|
240
|
+
}
|
241
|
+
end # #to_data
|
242
|
+
|
339
243
|
|
340
244
|
# @todo Document to_json method.
|
341
245
|
#
|
@@ -346,12 +250,12 @@ module Props
|
|
346
250
|
# @todo Document return value.
|
347
251
|
#
|
348
252
|
def to_json *args
|
349
|
-
|
253
|
+
to_data.to_json *args
|
350
254
|
end # #to_json
|
351
255
|
|
352
256
|
|
353
257
|
def to_yaml *args
|
354
|
-
|
258
|
+
to_data.to_yaml *args
|
355
259
|
end
|
356
260
|
|
357
261
|
|
@@ -360,4 +264,5 @@ end # module Props
|
|
360
264
|
end # module Meta
|
361
265
|
end # module NRSER
|
362
266
|
|
363
|
-
require_relative './props/
|
267
|
+
require_relative './props/prop'
|
268
|
+
require_relative './props/base'
|
@@ -33,29 +33,44 @@ module NRSER
|
|
33
33
|
NRSER.map_hash_values self, &block
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
# See {NRSER.transform_keys!}
|
37
37
|
def transform_keys! &block
|
38
38
|
return enum_for(:transform_keys!) { size } unless block_given?
|
39
39
|
NRSER.transform_keys! self, &block
|
40
40
|
end
|
41
41
|
|
42
42
|
|
43
|
+
# See {NRSER.transform_keys}
|
43
44
|
def transform_keys &block
|
44
45
|
return hash.enum_for(:transform_keys) { size } unless block_given?
|
45
46
|
NRSER.transform_keys self, &block
|
46
47
|
end
|
47
48
|
|
48
49
|
|
50
|
+
# See {NRSER.symbolize_keys!}
|
49
51
|
def symbolize_keys!
|
50
52
|
NRSER.symbolize_keys! self
|
51
53
|
end
|
52
54
|
|
53
55
|
|
56
|
+
# See {NRSER.symbolize_keys}
|
54
57
|
def symbolize_keys
|
55
58
|
NRSER.symbolize_keys self
|
56
59
|
end
|
57
60
|
|
58
61
|
|
62
|
+
# See {NRSER.stringify_keys!}
|
63
|
+
def stringify_keys!
|
64
|
+
NRSER.stringify_keys! self
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
# See {NRSER.stringify_keys}
|
69
|
+
def stringify_keys
|
70
|
+
NRSER.stringify_keys self
|
71
|
+
end
|
72
|
+
|
73
|
+
# See {NRSER.map_hash_keys}
|
59
74
|
def map_keys &block
|
60
75
|
NRSER.map_hash_keys self, &block
|
61
76
|
end
|
data/lib/nrser/string.rb
CHANGED
@@ -105,5 +105,55 @@ module NRSER
|
|
105
105
|
|
106
106
|
"#{str[0, stop]}#{omission}"
|
107
107
|
end
|
108
|
+
|
109
|
+
# Get the constant identified by a string.
|
110
|
+
#
|
111
|
+
# @example
|
112
|
+
#
|
113
|
+
# SomeClass == NRSER.constantize(SomeClass.name)
|
114
|
+
#
|
115
|
+
# Lifted from ActiveSupport.
|
116
|
+
#
|
117
|
+
# @param [String] camel_cased_word
|
118
|
+
# The constant's camel-cased, double-colon-separated "name",
|
119
|
+
# like "NRSER::Types::Array".
|
120
|
+
#
|
121
|
+
# @return [Object]
|
122
|
+
#
|
123
|
+
# @raise [NameError]
|
124
|
+
# When the name is not in CamelCase or is not initialized.
|
125
|
+
#
|
126
|
+
def constantize(camel_cased_word)
|
127
|
+
names = camel_cased_word.split('::')
|
128
|
+
|
129
|
+
# Trigger a built-in NameError exception including the ill-formed constant in the message.
|
130
|
+
Object.const_get(camel_cased_word) if names.empty?
|
131
|
+
|
132
|
+
# Remove the first blank element in case of '::ClassName' notation.
|
133
|
+
names.shift if names.size > 1 && names.first.empty?
|
134
|
+
|
135
|
+
names.inject(Object) do |constant, name|
|
136
|
+
if constant == Object
|
137
|
+
constant.const_get(name)
|
138
|
+
else
|
139
|
+
candidate = constant.const_get(name)
|
140
|
+
next candidate if constant.const_defined?(name, false)
|
141
|
+
next candidate unless Object.const_defined?(name)
|
142
|
+
|
143
|
+
# Go down the ancestors to check if it is owned directly. The check
|
144
|
+
# stops when we reach Object or the end of ancestors tree.
|
145
|
+
constant = constant.ancestors.inject do |const, ancestor|
|
146
|
+
break const if ancestor == Object
|
147
|
+
break ancestor if ancestor.const_defined?(name, false)
|
148
|
+
const
|
149
|
+
end
|
150
|
+
|
151
|
+
# owner is in Object, so raise
|
152
|
+
constant.const_get(name, false)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end # constantize
|
156
|
+
|
157
|
+
alias_method :to_const, :constantize
|
108
158
|
end # class << self
|
109
159
|
end # module NRSER
|
data/lib/nrser/types/hash.rb
CHANGED
data/lib/nrser/version.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
|
3
|
+
using NRSER::Types
|
4
4
|
|
5
5
|
describe NRSER::Meta::Props do
|
6
6
|
|
@@ -11,9 +11,9 @@ describe NRSER::Meta::Props do
|
|
11
11
|
Class.new(NRSER::Meta::Props::Base) do
|
12
12
|
# include NRSER::Meta::Props
|
13
13
|
|
14
|
-
prop :x, type:
|
15
|
-
prop :y, type:
|
16
|
-
prop :blah, type:
|
14
|
+
prop :x, type: t.int
|
15
|
+
prop :y, type: t.int
|
16
|
+
prop :blah, type: t.str, source: :blah
|
17
17
|
|
18
18
|
def blah
|
19
19
|
"blah!"
|
@@ -38,7 +38,7 @@ describe NRSER::Meta::Props do
|
|
38
38
|
expect(props[:blah].source?).to be true
|
39
39
|
expect(props[:blah].primary?).to be false
|
40
40
|
|
41
|
-
primary_props = point.props
|
41
|
+
primary_props = point.props only_primary: true
|
42
42
|
|
43
43
|
expect(primary_props.key? :blah).to be false
|
44
44
|
|
@@ -48,14 +48,14 @@ describe NRSER::Meta::Props do
|
|
48
48
|
expect(p.y).to be 2
|
49
49
|
|
50
50
|
expect(p.to_h).to eq({x: 1, y: 2, blah: "blah!"})
|
51
|
-
expect(p.to_h(
|
51
|
+
expect(p.to_h(only_primary: true)).to eq({x: 1, y: 2})
|
52
52
|
|
53
53
|
expect { point.new x: 1, y: 'why?' }.to raise_error TypeError
|
54
54
|
expect { p.x = 3 }.to raise_error NoMethodError
|
55
55
|
|
56
56
|
p_hash = p.to_h
|
57
57
|
|
58
|
-
p2 = point.
|
58
|
+
p2 = point.new p_hash
|
59
59
|
|
60
60
|
expect(p2.x).to be 1
|
61
61
|
expect(p2.y).to be 2
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nrser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- nrser
|
@@ -101,6 +101,7 @@ files:
|
|
101
101
|
- lib/nrser/meta/class_attrs.rb
|
102
102
|
- lib/nrser/meta/props.rb
|
103
103
|
- lib/nrser/meta/props/base.rb
|
104
|
+
- lib/nrser/meta/props/prop.rb
|
104
105
|
- lib/nrser/no_arg.rb
|
105
106
|
- lib/nrser/refinements.rb
|
106
107
|
- lib/nrser/refinements/array.rb
|