ryo.rb 0.5.5 → 0.5.7
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/.github/workflows/specs.yml +2 -2
- data/.rubocop.yml +2 -0
- data/README.md +46 -27
- data/lib/ryo/basic_object.rb +7 -11
- data/lib/ryo/builder.rb +35 -54
- data/lib/ryo/enumerable.rb +62 -79
- data/lib/ryo/json.rb +6 -11
- data/lib/ryo/keywords.rb +16 -28
- data/lib/ryo/object.rb +6 -10
- data/lib/ryo/reflect.rb +54 -170
- data/lib/ryo/utils.rb +68 -0
- data/lib/ryo/version.rb +1 -1
- data/lib/ryo/yaml.rb +6 -11
- data/lib/ryo.rb +26 -37
- data/ryo.rb.gemspec +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/1.0_prototypes_point_object.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/1.1_prototypes_ryo_fn.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/2.0_iteration_each.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/2.1_iteration_map.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/2.2_iteration_ancestors.rb +1 -0
- data/share/examples/ryo.rb/3.0_recursion_ryo_from.rb +20 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/3.1_recursion_ryo_from_with_array.rb +5 -4
- data/share/{ryo.rb/examples → examples/ryo.rb}/3.2_recursion_ryo_from_with_openstruct.rb +3 -3
- data/share/{ryo.rb/examples → examples/ryo.rb}/4.0_basicobject_ryo_basicobject.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/4.1_basicobject_ryo_basicobject_from.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/5_collisions_resolution_strategy.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/6_beyond_hash_objects.rb +1 -0
- data/share/{ryo.rb/examples → examples/ryo.rb}/7_ryo_memo.rb +1 -0
- data/share/ryo.rb/NEWS +11 -0
- data/spec/readme_spec.rb +2 -2
- data/spec/ryo_enumerable_spec.rb +1 -1
- data/spec/ryo_json_spec.rb +1 -1
- data/spec/ryo_keywords_spec.rb +1 -1
- data/spec/ryo_prototypes_spec.rb +1 -1
- data/spec/ryo_reflect_spec.rb +8 -0
- data/spec/ryo_spec.rb +1 -1
- data/spec/ryo_yaml_spec.rb +1 -1
- metadata +34 -18
- data/share/ryo.rb/examples/3.0_recursion_ryo_from.rb +0 -13
- /data/share/{ryo.rb/examples → examples/ryo.rb}/setup.rb +0 -0
- /data/{LICENSE → share/ryo.rb/LICENSE} +0 -0
data/lib/ryo/json.rb
CHANGED
@@ -1,45 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# The {Ryo::JSON Ryo::JSON} module provides a number of
|
5
|
-
# for coercing JSON data into a Ryo object.
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# The {Ryo::JSON Ryo::JSON} module provides a number of options
|
5
|
+
# for coercing JSON data into a Ryo object. The methods of
|
6
|
+
# this module are available on the {Ryo Ryo} module as singleton
|
7
|
+
# methods
|
8
8
|
module Ryo::JSON
|
9
|
-
require "json"
|
10
9
|
extend self
|
11
10
|
|
12
11
|
##
|
13
12
|
# @example
|
14
13
|
# Ryo.from_json(path: "/foo/bar/baz.json")
|
15
14
|
# Ryo.from_json(string: "[]")
|
16
|
-
#
|
17
15
|
# @param [String] path
|
18
16
|
# The path to a JSON file
|
19
|
-
#
|
20
17
|
# @param [String] string
|
21
18
|
# A blob of JSON
|
22
|
-
#
|
23
19
|
# @param [Ryo] object
|
24
20
|
# {Ryo::Object Ryo::Object}, or {Ryo::BasicObject Ryo::BasicObject}
|
25
21
|
# Defaults to {Ryo::Object Ryo::Object}
|
26
|
-
#
|
27
22
|
# @raise [SystemCallError]
|
28
23
|
# Might raise a number of Errno exceptions
|
29
|
-
#
|
30
24
|
# @return [Ryo::Object, Ryo::BasicObject]
|
31
25
|
# Returns a Ryo object
|
32
26
|
def from_json(path: nil, string: nil, object: Ryo::Object)
|
33
27
|
if path && string
|
34
28
|
raise ArgumentError, "Provide a path or string but not both"
|
35
29
|
elsif path
|
30
|
+
require "json" unless defined?(JSON)
|
36
31
|
object.from JSON.parse(File.binread(path))
|
37
32
|
elsif string
|
33
|
+
require "json" unless defined?(JSON)
|
38
34
|
object.from JSON.parse(string)
|
39
35
|
else
|
40
36
|
raise ArgumentError, "No path or string provided"
|
41
37
|
end
|
42
38
|
end
|
43
|
-
|
44
39
|
Ryo.extend(self)
|
45
40
|
end
|
data/lib/ryo/keywords.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
##
|
4
4
|
# The {Ryo::Keywords Ryo::Keywords} module implements Ryo equivalents
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# for some of JavaScript's keywords (eg: the **in** and **delete** operators).
|
6
|
+
# The instance methods of this module are available as singleton
|
7
7
|
# methods on the {Ryo} module.
|
8
8
|
module Ryo::Keywords
|
9
9
|
##
|
@@ -24,44 +24,32 @@ module Ryo::Keywords
|
|
24
24
|
alias_method :function, :fn
|
25
25
|
|
26
26
|
##
|
27
|
-
# Equivalent to JavaScript's **in** operator
|
28
|
-
#
|
27
|
+
# Equivalent to JavaScript's **in** operator
|
29
28
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
30
|
-
# A Ryo object
|
31
|
-
#
|
29
|
+
# A Ryo object
|
32
30
|
# @param [<String, #to_s>] property
|
33
|
-
# A property name
|
34
|
-
#
|
31
|
+
# A property name
|
35
32
|
# @return [Boolean]
|
36
|
-
# Returns true when **property** is a member of **ryo**, or its prototype chain
|
33
|
+
# Returns true when **property** is a member of **ryo**, or its prototype chain
|
37
34
|
def in?(ryo, property)
|
38
35
|
return false unless ryo
|
39
36
|
property?(ryo, property) || in?(prototype_of(ryo), property)
|
40
37
|
end
|
41
38
|
|
42
39
|
##
|
43
|
-
# The {#delete} method deletes a property from a Ryo object
|
44
|
-
#
|
45
|
-
#
|
46
|
-
# @note
|
47
|
-
# This method does not delete properties from the prototype(s)
|
48
|
-
# of a Ryo object. <br>
|
49
|
-
# For that - see {Ryo::Reflect#delete! Ryo::Reflect#delete!}.
|
50
|
-
#
|
40
|
+
# The {#delete} method deletes a property from a Ryo object
|
41
|
+
# @see Ryo::Reflect#delete!
|
51
42
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
52
|
-
# A Ryo object
|
53
|
-
#
|
43
|
+
# A Ryo object
|
54
44
|
# @param [<String, #to_s>] property
|
55
|
-
# A property name
|
56
|
-
#
|
45
|
+
# A property name
|
46
|
+
# @param [Integer] ancestors
|
47
|
+
# The number of prototypes to traverse.
|
48
|
+
# Defaults to the entire prototype chain.
|
57
49
|
# @return [void]
|
58
|
-
def delete(ryo, property)
|
59
|
-
|
60
|
-
|
61
|
-
table_of(ryo).delete(property)
|
62
|
-
else
|
63
|
-
return if getter_defined?(ryo, property)
|
64
|
-
define_method!(ryo, property) { ryo[property] }
|
50
|
+
def delete(ryo, property, ancestors: nil)
|
51
|
+
each_ryo(ryo, ancestors:) do
|
52
|
+
Ryo.property?(_1, property) ? table_of(_1).delete(property) : nil
|
65
53
|
end
|
66
54
|
end
|
67
55
|
end
|
data/lib/ryo/object.rb
CHANGED
@@ -10,19 +10,17 @@ class Ryo::Object
|
|
10
10
|
##
|
11
11
|
# @param props (see Ryo::Builder.build)
|
12
12
|
# @param prototype (see Ryo::Builder.build)
|
13
|
-
#
|
14
13
|
# @return [Ryo::Object]
|
15
|
-
# Returns an instance of {Ryo::Object Ryo::Object}
|
14
|
+
# Returns an instance of {Ryo::Object Ryo::Object}
|
16
15
|
def self.create(props, prototype = nil)
|
17
16
|
Ryo::Builder.build(self, props, prototype)
|
18
17
|
end
|
19
18
|
|
20
19
|
##
|
21
|
-
# Creates a Ryo object by recursively walking a Hash object
|
20
|
+
# Creates a Ryo object by recursively walking a Hash object
|
22
21
|
#
|
23
22
|
# @param props (see Ryo::Builder.recursive_build)
|
24
23
|
# @param prototype (see Ryo::Builder.recursive_build)
|
25
|
-
#
|
26
24
|
# @return [Ryo::Object]
|
27
25
|
# Returns an instance of {Ryo::Object Ryo::Object}.
|
28
26
|
def self.from(props, prototype = nil)
|
@@ -30,13 +28,12 @@ class Ryo::Object
|
|
30
28
|
end
|
31
29
|
|
32
30
|
##
|
33
|
-
# Duplicates the internals of a Ryo object
|
31
|
+
# Duplicates the internals of a Ryo object
|
34
32
|
#
|
35
33
|
# @param [Ryo::Object] ryo
|
36
|
-
# A Ryo object
|
37
|
-
#
|
34
|
+
# A Ryo object
|
38
35
|
# @return [Ryo::Object]
|
39
|
-
# Returns a Ryo object
|
36
|
+
# Returns a Ryo object
|
40
37
|
def initialize_dup(ryo)
|
41
38
|
Ryo.set_table_of(self, Ryo.table_of(ryo).dup)
|
42
39
|
Ryo.extend!(self, Ryo)
|
@@ -50,9 +47,8 @@ end
|
|
50
47
|
#
|
51
48
|
# @param props (see Ryo::Builder.build)
|
52
49
|
# @param prototype (see Ryo::Builder.build)
|
53
|
-
#
|
54
50
|
# @return [Ryo::Object]
|
55
|
-
# Returns an instance of {Ryo::Object Ryo::Object}
|
51
|
+
# Returns an instance of {Ryo::Object Ryo::Object}
|
56
52
|
def Ryo.Object(props, prototype = nil)
|
57
53
|
Ryo::Object.create(props, prototype)
|
58
54
|
end
|
data/lib/ryo/reflect.rb
CHANGED
@@ -1,14 +1,16 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# The {Ryo::Reflect Ryo::Reflect} module
|
5
|
-
#
|
6
|
-
# and
|
7
|
-
# [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
4
|
+
# The {Ryo::Reflect Ryo::Reflect} module mirrors
|
5
|
+
# JavaScript's [`Relfect` object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect),
|
6
|
+
# and some of the static methods on JavaScript's
|
7
|
+
# [`Object`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
|
8
|
+
# as well.
|
8
9
|
#
|
9
|
-
#
|
10
|
-
# instance methods of this module
|
11
|
-
# on the {Ryo Ryo}
|
10
|
+
# {Ryo::Reflect Ryo::Reflect} also implements Ryo-specific
|
11
|
+
# reflection features. The instance methods of this module
|
12
|
+
# are available as singleton methods on the {Ryo Ryo}
|
13
|
+
# module.
|
12
14
|
module Ryo::Reflect
|
13
15
|
extend self
|
14
16
|
|
@@ -16,7 +18,7 @@ module Ryo::Reflect
|
|
16
18
|
# @group JavaScript equivalents (Reflect)
|
17
19
|
|
18
20
|
##
|
19
|
-
# Equivalent to JavaScript's `Reflect.getPrototypeOf
|
21
|
+
# Equivalent to JavaScript's `Reflect.getPrototypeOf`
|
20
22
|
#
|
21
23
|
# @param [Ryo] ryo
|
22
24
|
# A Ryo object.
|
@@ -29,7 +31,7 @@ module Ryo::Reflect
|
|
29
31
|
end
|
30
32
|
|
31
33
|
##
|
32
|
-
# Equivalent to JavaScript's `Reflect.setPrototypeOf
|
34
|
+
# Equivalent to JavaScript's `Reflect.setPrototypeOf`
|
33
35
|
#
|
34
36
|
# @param [Ryo] ryo
|
35
37
|
# A Ryo object.
|
@@ -45,17 +47,14 @@ module Ryo::Reflect
|
|
45
47
|
end
|
46
48
|
|
47
49
|
##
|
48
|
-
# Equivalent to JavaScript's `Reflect.defineProperty
|
50
|
+
# Equivalent to JavaScript's `Reflect.defineProperty`
|
49
51
|
#
|
50
52
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
51
|
-
# A Ryo object
|
52
|
-
#
|
53
|
+
# A Ryo object
|
53
54
|
# @param [<String, #to_s>] property
|
54
|
-
# The name of
|
55
|
-
#
|
55
|
+
# The name of a property
|
56
56
|
# @param [Object, BasicObject] value
|
57
|
-
# The value
|
58
|
-
#
|
57
|
+
# The property's value
|
59
58
|
# @return [void]
|
60
59
|
def define_property(ryo, property, value)
|
61
60
|
table, property = table_of(ryo), property.to_s
|
@@ -76,13 +75,12 @@ module Ryo::Reflect
|
|
76
75
|
|
77
76
|
##
|
78
77
|
# Equivalent to JavaScript's `Reflect.ownKeys`, and
|
79
|
-
# JavaScript's `Object.keys
|
78
|
+
# JavaScript's `Object.keys`
|
80
79
|
#
|
81
80
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
82
|
-
# A Ryo object
|
83
|
-
#
|
81
|
+
# A Ryo object
|
84
82
|
# @return [Array<String>]
|
85
|
-
# Returns the properties defined on a Ryo object
|
83
|
+
# Returns the properties defined on a Ryo object
|
86
84
|
def properties_of(ryo)
|
87
85
|
table_of(ryo).keys
|
88
86
|
end
|
@@ -97,13 +95,11 @@ module Ryo::Reflect
|
|
97
95
|
# and `Object.prototype.hasOwnProperty`.
|
98
96
|
#
|
99
97
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
100
|
-
# A Ryo object
|
101
|
-
#
|
98
|
+
# A Ryo object
|
102
99
|
# @param [<String, #to_s>] property
|
103
|
-
#
|
104
|
-
#
|
100
|
+
# The name of a property
|
105
101
|
# @return [Boolean]
|
106
|
-
# Returns true when
|
102
|
+
# Returns true when the property is a member of a Ryo object
|
107
103
|
def property?(ryo, property)
|
108
104
|
table_of(ryo).key?(property.to_s)
|
109
105
|
end
|
@@ -111,14 +107,11 @@ module Ryo::Reflect
|
|
111
107
|
##
|
112
108
|
# Equivalent to JavaScript's `Object.assign`.
|
113
109
|
#
|
114
|
-
#
|
115
110
|
# @param [Ryo, Hash, #to_hash] target
|
116
|
-
# The target object
|
117
|
-
#
|
111
|
+
# The target object
|
118
112
|
# @param [Ryo, Hash, #to_hash] sources
|
119
113
|
# A variable number of source objects that
|
120
|
-
# will be merged
|
121
|
-
#
|
114
|
+
# will be merged with the target object
|
122
115
|
# @return [Ryo]
|
123
116
|
# Returns the modified target object.
|
124
117
|
def assign(target, *sources)
|
@@ -133,30 +126,10 @@ module Ryo::Reflect
|
|
133
126
|
# @group Ryo-specific
|
134
127
|
|
135
128
|
##
|
136
|
-
# The {#delete!} method deletes a property from a Ryo object,
|
137
|
-
# and from the prototypes in its prototype chain.
|
138
|
-
#
|
139
|
-
# @see Ryo::Keywords#delete
|
140
|
-
#
|
141
129
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
142
|
-
# A Ryo object
|
143
|
-
#
|
144
|
-
# @param [<String, #to_s>] property
|
145
|
-
# A property name.
|
146
|
-
#
|
147
|
-
# @return [void]
|
148
|
-
def delete!(ryo, property)
|
149
|
-
[ryo, *prototype_chain_of(ryo)].each do
|
150
|
-
Ryo.delete(_1, property.to_s)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
##
|
155
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
156
|
-
# A Ryo object.
|
157
|
-
#
|
130
|
+
# A Ryo object
|
158
131
|
# @return [Array<Ryo::Object, Ryo::BasicObject>]
|
159
|
-
# Returns the prototype chain of a Ryo object
|
132
|
+
# Returns the prototype chain of a Ryo object
|
160
133
|
def prototype_chain_of(ryo)
|
161
134
|
prototypes = []
|
162
135
|
loop do
|
@@ -169,20 +142,21 @@ module Ryo::Reflect
|
|
169
142
|
|
170
143
|
##
|
171
144
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
172
|
-
# A Ryo object
|
173
|
-
#
|
145
|
+
# A Ryo object
|
174
146
|
# @param [Boolean] recursive
|
175
147
|
# When true, nested Ryo objects are replaced by
|
176
|
-
# their table as well
|
177
|
-
#
|
148
|
+
# their table as well
|
178
149
|
# @return [Hash]
|
179
|
-
# Returns the table of a Ryo object
|
150
|
+
# Returns the table of a Ryo object
|
180
151
|
def table_of(ryo, recursive: false)
|
181
152
|
table = kernel(:instance_variable_get).bind_call(ryo, :@_table)
|
182
153
|
if recursive
|
183
154
|
table.each do |key, value|
|
184
155
|
if ryo?(value)
|
185
156
|
table[key] = table_of(value, recursive:)
|
157
|
+
elsif value.respond_to?(:each)
|
158
|
+
table[key] = value.respond_to?(:each_pair) ?
|
159
|
+
value : value.map { table_of(_1, recursive:) }
|
186
160
|
end
|
187
161
|
end
|
188
162
|
end
|
@@ -190,14 +164,12 @@ module Ryo::Reflect
|
|
190
164
|
end
|
191
165
|
|
192
166
|
##
|
193
|
-
# Sets the table of a Ryo object
|
167
|
+
# Sets the table of a Ryo object
|
194
168
|
#
|
195
169
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
196
|
-
# A Ryo object
|
197
|
-
#
|
170
|
+
# A Ryo object
|
198
171
|
# @param [Hash] table
|
199
|
-
# The table
|
200
|
-
#
|
172
|
+
# The table
|
201
173
|
# @return [nil]
|
202
174
|
def set_table_of(ryo, table)
|
203
175
|
kernel(:instance_variable_set)
|
@@ -207,51 +179,42 @@ module Ryo::Reflect
|
|
207
179
|
|
208
180
|
##
|
209
181
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
210
|
-
# A Ryo object
|
211
|
-
#
|
182
|
+
# A Ryo object
|
212
183
|
# @param [<String, Symbol>] method
|
213
|
-
# The name of a method
|
214
|
-
#
|
184
|
+
# The name of a method
|
215
185
|
# @param [::Object, ::BasicObject] args
|
216
|
-
# Zero or more
|
217
|
-
#
|
186
|
+
# Zero or more method arguments
|
218
187
|
# @param [Proc] b
|
219
|
-
# An optional block
|
220
|
-
#
|
188
|
+
# An optional block
|
221
189
|
# @return [::Object, ::BasicObject]
|
222
|
-
|
223
|
-
def call_method(ryo, method, *, &b)
|
190
|
+
def call_method(ryo, method, *args, &b)
|
224
191
|
kernel(:__send__)
|
225
|
-
.bind_call(ryo, method,
|
192
|
+
.bind_call(ryo, method, *args, &b)
|
226
193
|
end
|
227
194
|
|
228
195
|
##
|
229
196
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
230
|
-
# A Ryo object
|
231
|
-
#
|
197
|
+
# A Ryo object
|
232
198
|
# @return [Class]
|
233
|
-
# Returns the class of a Ryo object
|
199
|
+
# Returns the class of a Ryo object
|
234
200
|
def class_of(ryo)
|
235
201
|
kernel(:class).bind_call(ryo)
|
236
202
|
end
|
237
203
|
|
238
204
|
##
|
239
205
|
# @param [Ryo::Function, Object, BasicObject] obj
|
240
|
-
# An object
|
241
|
-
#
|
206
|
+
# An object
|
242
207
|
# @return [Boolean]
|
243
|
-
# Returns true when
|
208
|
+
# Returns true when given a Ryo function
|
244
209
|
def function?(obj)
|
245
210
|
Ryo::Function === obj
|
246
211
|
end
|
247
212
|
|
248
213
|
##
|
249
214
|
# @param [Ryo::Function, Object, BasicObject] obj
|
250
|
-
# An object
|
251
|
-
#
|
215
|
+
# An object
|
252
216
|
# @return [Boolean]
|
253
|
-
# Returns true when
|
254
|
-
# of {Ryo::Memo Ryo::Memo}.
|
217
|
+
# Returns true when given a Ryo memo
|
255
218
|
def memo?(obj)
|
256
219
|
Ryo::Memo === obj
|
257
220
|
end
|
@@ -264,33 +227,29 @@ module Ryo::Reflect
|
|
264
227
|
# Ryo.ryo?(Object.new) # => false
|
265
228
|
#
|
266
229
|
# @param [Object, BasicObject] obj
|
267
|
-
# An object
|
268
|
-
#
|
230
|
+
# An object
|
269
231
|
# @return [Boolean]
|
270
|
-
# Returns true when
|
232
|
+
# Returns true when given a Ryo object
|
271
233
|
def ryo?(obj)
|
272
234
|
Ryo === obj
|
273
235
|
end
|
274
236
|
|
275
237
|
##
|
276
238
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo1
|
277
|
-
# A Ryo object
|
278
|
-
#
|
239
|
+
# A Ryo object
|
279
240
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo2
|
280
|
-
# A Ryo object
|
281
|
-
#
|
241
|
+
# A Ryo object
|
282
242
|
# @return [Boolean]
|
283
|
-
# Returns true when two Ryo objects are
|
243
|
+
# Returns true when the two Ryo objects are strictly equal
|
284
244
|
def equal?(ryo1, ryo2)
|
285
245
|
kernel(:equal?).bind_call(ryo1, ryo2)
|
286
246
|
end
|
287
247
|
|
288
248
|
##
|
289
249
|
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
290
|
-
# A Ryo object
|
291
|
-
#
|
250
|
+
# A Ryo object
|
292
251
|
# @return [String]
|
293
|
-
# Returns a String representation of a Ryo object
|
252
|
+
# Returns a String representation of a Ryo object
|
294
253
|
def inspect_object(ryo)
|
295
254
|
format(
|
296
255
|
"#<Ryo object=%{object} proto=%{proto} table=%{table}>",
|
@@ -301,80 +260,5 @@ module Ryo::Reflect
|
|
301
260
|
end
|
302
261
|
# @endgroup
|
303
262
|
|
304
|
-
|
305
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
306
|
-
# A Ryo object.
|
307
|
-
#
|
308
|
-
# @param [<String, Symbol>] method
|
309
|
-
# The name of the method.
|
310
|
-
#
|
311
|
-
# @param [Proc] b
|
312
|
-
# The method's body.
|
313
|
-
#
|
314
|
-
# @private
|
315
|
-
private def define_method!(ryo, method, &b)
|
316
|
-
kernel(:define_singleton_method)
|
317
|
-
.bind_call(ryo, method, &b)
|
318
|
-
end
|
319
|
-
|
320
|
-
##
|
321
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
322
|
-
# A Ryo object.
|
323
|
-
#
|
324
|
-
# @param [<String, #to_s>] property
|
325
|
-
# The name of the property.
|
326
|
-
#
|
327
|
-
# @return [Boolean]
|
328
|
-
# Returns true when the property has been
|
329
|
-
# defined with a getter method.
|
330
|
-
#
|
331
|
-
# @private
|
332
|
-
private def getter_defined?(ryo, property)
|
333
|
-
kernel(:method)
|
334
|
-
.bind_call(ryo, property)
|
335
|
-
.source_location
|
336
|
-
&.dig(0) == __FILE__
|
337
|
-
end
|
338
|
-
|
339
|
-
##
|
340
|
-
#
|
341
|
-
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
342
|
-
# A Ryo object.
|
343
|
-
#
|
344
|
-
# @param [<String, #to_s>] property
|
345
|
-
# The name of the property.
|
346
|
-
#
|
347
|
-
# @return [Boolean]
|
348
|
-
# Returns true when the property has been
|
349
|
-
# defined with a setter method.
|
350
|
-
#
|
351
|
-
# @private
|
352
|
-
private def setter_defined?(ryo, property)
|
353
|
-
getter_defined?(ryo, "#{property}=")
|
354
|
-
end
|
355
|
-
|
356
|
-
##
|
357
|
-
# @private
|
358
|
-
private def merge!(obj1, obj2)
|
359
|
-
obj1, obj2 = to_hash(obj1), to_hash(obj2)
|
360
|
-
obj2.each { obj1[_1.to_s] = _2 }
|
361
|
-
obj1
|
362
|
-
end
|
363
|
-
|
364
|
-
##
|
365
|
-
# @private
|
366
|
-
private def to_hash(obj)
|
367
|
-
if ryo?(obj)
|
368
|
-
table_of(obj)
|
369
|
-
else
|
370
|
-
Hash.try_convert(obj)
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
##
|
375
|
-
# @private
|
376
|
-
def kernel(name)
|
377
|
-
Module.instance_method(name)
|
378
|
-
end
|
379
|
-
# @endgroup
|
263
|
+
include Ryo::Utils
|
380
264
|
end
|
data/lib/ryo/utils.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# The {Ryo::Utils Ryo::Utils} module provides utility
|
5
|
+
# methods that are internal to Ryo. This module
|
6
|
+
# and its methods should not be used directly.
|
7
|
+
# @api private
|
8
|
+
module Ryo::Utils
|
9
|
+
private
|
10
|
+
|
11
|
+
##
|
12
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
13
|
+
# A Ryo object
|
14
|
+
# @param [<String, Symbol>] method
|
15
|
+
# The name of a method
|
16
|
+
# @param [Proc] b
|
17
|
+
# The method's implementation
|
18
|
+
def define_method!(ryo, method, &b)
|
19
|
+
kernel(:define_singleton_method)
|
20
|
+
.bind_call(ryo, method, &b)
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
25
|
+
# A Ryo object
|
26
|
+
# @param [<String, #to_s>] property
|
27
|
+
# The name of a property
|
28
|
+
# @return [Boolean]
|
29
|
+
# Returns true for a Ryo property that has a
|
30
|
+
# corresponding getter method implemented by Ryo
|
31
|
+
def getter_defined?(ryo, property)
|
32
|
+
path = kernel(:method)
|
33
|
+
.bind_call(ryo, property)
|
34
|
+
.source_location
|
35
|
+
&.dig(0)
|
36
|
+
path ? File.dirname(path) == File.dirname(__FILE__) : false
|
37
|
+
end
|
38
|
+
|
39
|
+
##
|
40
|
+
# @param [<Ryo::Object, Ryo::BasicObject>] ryo
|
41
|
+
# A Ryo object
|
42
|
+
# @param [<String, #to_s>] property
|
43
|
+
# The name of a property
|
44
|
+
# @return [Boolean]
|
45
|
+
# Returns true for a Ryo property that has a
|
46
|
+
# corresponding setter method implemented by Ryo
|
47
|
+
def setter_defined?(ryo, property)
|
48
|
+
getter_defined?(ryo, "#{property}=")
|
49
|
+
end
|
50
|
+
|
51
|
+
def merge!(obj1, obj2)
|
52
|
+
obj1, obj2 = to_hash(obj1), to_hash(obj2)
|
53
|
+
obj2.each { obj1[_1.to_s] = _2 }
|
54
|
+
obj1
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_hash(obj)
|
58
|
+
if ryo?(obj)
|
59
|
+
table_of(obj)
|
60
|
+
else
|
61
|
+
Hash.try_convert(obj)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def kernel(name)
|
66
|
+
Module.instance_method(name)
|
67
|
+
end
|
68
|
+
end
|
data/lib/ryo/version.rb
CHANGED
data/lib/ryo/yaml.rb
CHANGED
@@ -1,45 +1,40 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# The {Ryo::YAML Ryo::YAML} module provides a number of
|
5
|
-
# for coercing YAML data into a Ryo object.
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# The {Ryo::YAML Ryo::YAML} module provides a number of options
|
5
|
+
# for coercing YAML data into a Ryo object. The methods of
|
6
|
+
# this module are available as singleton methods on the {Ryo Ryo}
|
7
|
+
# module
|
8
8
|
module Ryo::YAML
|
9
|
-
require "yaml"
|
10
9
|
extend self
|
11
10
|
|
12
11
|
##
|
13
12
|
# @example
|
14
13
|
# Ryo.from_yaml(path: "/foo/bar/baz.yaml")
|
15
14
|
# Ryo.from_yaml(string: "---\nfoo: bar\n")
|
16
|
-
#
|
17
15
|
# @param [String] path
|
18
16
|
# The path to a YAML file
|
19
|
-
#
|
20
17
|
# @param [String] string
|
21
18
|
# A blob of YAML
|
22
|
-
#
|
23
19
|
# @param [Ryo] object
|
24
20
|
# {Ryo::Object Ryo::Object}, or {Ryo::BasicObject Ryo::BasicObject}
|
25
21
|
# Defaults to {Ryo::Object Ryo::Object}
|
26
|
-
#
|
27
22
|
# @raise [SystemCallError]
|
28
23
|
# Might raise a number of Errno exceptions
|
29
|
-
#
|
30
24
|
# @return [Ryo::Object, Ryo::BasicObject]
|
31
25
|
# Returns a Ryo object
|
32
26
|
def from_yaml(path: nil, string: nil, object: Ryo::Object)
|
33
27
|
if path && string
|
34
28
|
raise ArgumentError, "Provide a path or string but not both"
|
35
29
|
elsif path
|
30
|
+
require "yaml" unless defined?(YAML)
|
36
31
|
object.from YAML.load_file(path)
|
37
32
|
elsif string
|
33
|
+
require "yaml" unless defined?(YAML)
|
38
34
|
object.from YAML.load(string)
|
39
35
|
else
|
40
36
|
raise ArgumentError, "No path or string provided"
|
41
37
|
end
|
42
38
|
end
|
43
|
-
|
44
39
|
Ryo.extend(self)
|
45
40
|
end
|