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