ryo.rb 0.5.3 → 0.5.6
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/README.md +30 -14
- data/Rakefile.rb +13 -0
- 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/object.rb +6 -10
- data/lib/ryo/reflect.rb +55 -155
- data/lib/ryo/utils.rb +68 -0
- data/lib/ryo/version.rb +1 -1
- data/lib/ryo/yaml.rb +45 -0
- data/lib/ryo.rb +24 -37
- data/ryo.rb.gemspec +1 -0
- data/share/ryo.rb/examples/1.0_prototypes_point_object.rb +1 -0
- data/share/ryo.rb/examples/1.1_prototypes_ryo_fn.rb +1 -0
- data/share/ryo.rb/examples/2.0_iteration_each.rb +1 -0
- data/share/ryo.rb/examples/2.1_iteration_map.rb +1 -0
- data/share/ryo.rb/examples/2.2_iteration_ancestors.rb +1 -0
- data/share/ryo.rb/examples/3.0_recursion_ryo_from.rb +1 -0
- data/share/ryo.rb/examples/3.1_recursion_ryo_from_with_array.rb +1 -0
- data/share/ryo.rb/examples/3.2_recursion_ryo_from_with_openstruct.rb +1 -0
- data/share/ryo.rb/examples/4.0_basicobject_ryo_basicobject.rb +1 -0
- data/share/ryo.rb/examples/4.1_basicobject_ryo_basicobject_from.rb +1 -0
- data/share/ryo.rb/examples/5_collisions_resolution_strategy.rb +1 -0
- data/share/ryo.rb/examples/6_beyond_hash_objects.rb +1 -0
- data/share/ryo.rb/examples/7_ryo_memo.rb +1 -0
- data/spec/ryo_enumerable_spec.rb +1 -1
- data/spec/ryo_json_spec.rb +31 -13
- data/spec/ryo_reflect_spec.rb +8 -0
- data/spec/ryo_spec.rb +1 -1
- data/spec/ryo_yaml_spec.rb +44 -0
- metadata +8 -5
- data/.gitlab-ci.yml +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae979c4fc47c5c25d26b0c215807a7ebd867dc5abd596277dda692c36c5c3445
|
4
|
+
data.tar.gz: 3cf89103180d9d6280698b93520eb80dc9af2e3ff4cbebb84c54b1089bed12e6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 795a2ab471038483d47fa39103996ec756da3437098b27091bb3b6e1f6534202ebc508e33f8d38bda4dfee8ae835465947da0c8adb2c13805480f13b4f54f4fe
|
7
|
+
data.tar.gz: edd4fd919629134e9479a91469084dbbdaf5507ce6aef91b7e1779720bff76ad1aec675dd31de42a05c7a8375d4c0ca27ce5aba260059b18fa526ec755bc7a0a
|
data/.github/workflows/specs.yml
CHANGED
@@ -12,7 +12,7 @@ jobs:
|
|
12
12
|
fail-fast: false
|
13
13
|
matrix:
|
14
14
|
os: [ubuntu-latest]
|
15
|
-
ruby: [3.
|
15
|
+
ruby: [3.2, 3.3]
|
16
16
|
runs-on: ${{ matrix.os }}
|
17
17
|
steps:
|
18
18
|
- uses: actions/checkout@v2
|
@@ -20,4 +20,4 @@ jobs:
|
|
20
20
|
with:
|
21
21
|
ruby-version: ${{ matrix.ruby }}
|
22
22
|
- run: bundle install
|
23
|
-
- run:
|
23
|
+
- run: rake ci
|
data/README.md
CHANGED
@@ -16,6 +16,7 @@ method seen in the example returns an instance of
|
|
16
16
|
[Ryo::Object](https://0x1eef.github.io/x/ryo.rb/Ryo/Object.html):
|
17
17
|
|
18
18
|
```ruby
|
19
|
+
#!/usr/bin/env ruby
|
19
20
|
require "ryo"
|
20
21
|
|
21
22
|
point_x = Ryo(x: 5)
|
@@ -35,6 +36,7 @@ will bind its `self` to the Ryo object it is assigned to, and when the function
|
|
35
36
|
is called it will have access to the properties of the Ryo object:
|
36
37
|
|
37
38
|
```ruby
|
39
|
+
#!/usr/bin/env ruby
|
38
40
|
require "ryo"
|
39
41
|
|
40
42
|
point_x = Ryo(x: 5)
|
@@ -56,6 +58,7 @@ The following example demonstrates
|
|
56
58
|
accessed for the first time. It is similar to a Ryo function:
|
57
59
|
|
58
60
|
```ruby
|
61
|
+
#!/usr/bin/env ruby
|
59
62
|
require "ryo"
|
60
63
|
|
61
64
|
point_x = Ryo(x: Ryo.memo { 5 })
|
@@ -87,6 +90,7 @@ is not implemented directly on a Ryo object.
|
|
87
90
|
A demonstration of [`Ryo.each`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#each-class_method):
|
88
91
|
|
89
92
|
```ruby
|
93
|
+
#!/usr/bin/env ruby
|
90
94
|
require "ryo"
|
91
95
|
|
92
96
|
point = Ryo(x: 10, y: 20)
|
@@ -115,6 +119,7 @@ and it returns a new copy of a Ryo object and its prototypes.
|
|
115
119
|
A demonstration of [`Ryo.map!`](http://0x1eef.github.io/x/ryo.rb/Ryo/Enumerable.html#map!-instance_method):
|
116
120
|
|
117
121
|
```ruby
|
122
|
+
#!/usr/bin/env ruby
|
118
123
|
require "ryo"
|
119
124
|
|
120
125
|
point_x = Ryo(x: 2)
|
@@ -148,6 +153,7 @@ demonstrates using the `ancestors` option with
|
|
148
153
|
[`Ryo.find`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#find-class_method):
|
149
154
|
|
150
155
|
```ruby
|
156
|
+
#!/usr/bin/env ruby
|
151
157
|
require "ryo"
|
152
158
|
|
153
159
|
point_x = Ryo(x: 5)
|
@@ -174,6 +180,7 @@ very large - otherwise there shouldn't be a noticeable performance impact.
|
|
174
180
|
The following example demonstrates [`Ryo.from`](https://0x1eef.github.io/x/ryo.rb/Ryo.html#from-class_method):
|
175
181
|
|
176
182
|
```ruby
|
183
|
+
#!/usr/bin/env ruby
|
177
184
|
require "ryo"
|
178
185
|
|
179
186
|
point = Ryo.from({
|
@@ -194,6 +201,7 @@ An object that can't be turned into a Ryo object is left as-is. The following
|
|
194
201
|
example demonstrates how that works in practice:
|
195
202
|
|
196
203
|
``` ruby
|
204
|
+
#!/usr/bin/env ruby
|
197
205
|
require "ryo"
|
198
206
|
|
199
207
|
points = Ryo.from([
|
@@ -221,6 +229,7 @@ can recursively turn an OpenStruct object into Ryo objects. The example also ass
|
|
221
229
|
a prototype to the Ryo object created from the OpenStruct:
|
222
230
|
|
223
231
|
``` ruby
|
232
|
+
#!/usr/bin/env ruby
|
224
233
|
require "ryo"
|
225
234
|
require "ostruct"
|
226
235
|
|
@@ -246,6 +255,7 @@ with fewer methods. The following example demonstrates
|
|
246
255
|
how to create an instance of [Ryo::BasicObject](https://0x1eef.github.io/x/ryo.rb/Ryo/BasicObject.html):
|
247
256
|
|
248
257
|
```ruby
|
258
|
+
#!/usr/bin/env ruby
|
249
259
|
require "ryo"
|
250
260
|
|
251
261
|
point_x = Ryo::BasicObject(x: 0)
|
@@ -265,6 +275,7 @@ it returns instance(s) of [Ryo::BasicObject](https://0x1eef.github.io/x/ryo.rb/R
|
|
265
275
|
instead:
|
266
276
|
|
267
277
|
```ruby
|
278
|
+
#!/usr/bin/env ruby
|
268
279
|
require "ryo"
|
269
280
|
|
270
281
|
point = Ryo::BasicObject.from({
|
@@ -281,18 +292,21 @@ p [point.x.to_i, point.y.to_i]
|
|
281
292
|
|
282
293
|
#### Resolution strategy
|
283
294
|
|
284
|
-
When a property and method collide, Ryo tries to
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
295
|
+
When a property and method collide, Ryo tries to
|
296
|
+
find the best resolution. Since Ryo properties don't
|
297
|
+
accept arguments, and methods can - we are able to
|
298
|
+
distinguish a method from a Ryo property by the presence
|
299
|
+
or absence of an argument. Consider the following example,
|
300
|
+
where a property collides with the `Kernel#then` method:
|
290
301
|
|
291
302
|
```ruby
|
303
|
+
#!/usr/bin/env ruby
|
292
304
|
require "ryo"
|
293
305
|
|
294
306
|
ryo = Ryo::Object(then: 12)
|
307
|
+
# Resolves to Ryo property
|
295
308
|
p ryo.then # => 12
|
309
|
+
# Resolves to Kernel#then
|
296
310
|
p ryo.then { 34 } # => 34
|
297
311
|
```
|
298
312
|
|
@@ -300,20 +314,22 @@ p ryo.then { 34 } # => 34
|
|
300
314
|
|
301
315
|
#### Duck typing
|
302
316
|
|
303
|
-
The documentation has used simple terms to describe
|
304
|
-
with: Hash and Array objects.
|
305
|
-
that
|
306
|
-
|
317
|
+
The documentation has used simple terms to describe
|
318
|
+
the objects that Ryo works with: Hash and Array objects.
|
319
|
+
But that doesn't quite capture the fact that Ryo
|
320
|
+
uses duck typing: any object that implements `#each_pair`
|
321
|
+
is similar to a Hash, and any object that implements
|
322
|
+
`#each` is similar to an Array. Note that only
|
307
323
|
[Ryo.from](https://0x1eef.github.io/x/ryo.rb/Ryo.html#from-class_method),
|
308
324
|
[Ryo::Object.from](https://0x1eef.github.io/x/ryo.rb/Ryo/Object.html#from-class_method)
|
309
325
|
and
|
310
326
|
[Ryo::BasicObject.from](https://0x1eef.github.io/x/ryo.rb/Ryo/BasicObject.html#from-class_method)
|
311
|
-
can handle Array
|
327
|
+
can handle Array-like objects.
|
312
328
|
|
313
|
-
|
314
|
-
`#each_pair`, into a Ryo object:
|
329
|
+
The following example implements `#each_pair`:
|
315
330
|
|
316
331
|
``` ruby
|
332
|
+
#!/usr/bin/env ruby
|
317
333
|
require "ryo"
|
318
334
|
|
319
335
|
class Point
|
@@ -353,7 +369,7 @@ Ryo can be installed via rubygems.org:
|
|
353
369
|
|
354
370
|
Thanks to
|
355
371
|
[@awfulcooking (mooff)](https://github.com/awfulcooking)
|
356
|
-
for the helpful discussions
|
372
|
+
for the helpful discussions
|
357
373
|
|
358
374
|
## License
|
359
375
|
|
data/Rakefile.rb
ADDED
data/lib/ryo/basic_object.rb
CHANGED
@@ -10,33 +10,30 @@ class Ryo::BasicObject < BasicObject
|
|
10
10
|
##
|
11
11
|
# @param props (see Ryo::Builder.build)
|
12
12
|
# @param prototype (see Ryo::Builder.build)
|
13
|
-
#
|
14
13
|
# @return [Ryo::BasicObject]
|
15
|
-
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
14
|
+
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
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::BasicObject]
|
27
|
-
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
25
|
+
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
28
26
|
def self.from(props, prototype = nil)
|
29
27
|
::Ryo::Builder.recursive_build(self, props, prototype)
|
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::BasicObject] ryo
|
36
|
-
# A Ryo object
|
37
|
-
#
|
34
|
+
# A Ryo object
|
38
35
|
# @return [Ryo::BasicObject]
|
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::BasicObject]
|
55
|
-
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
51
|
+
# Returns an instance of {Ryo::BasicObject Ryo::BasicObject}
|
56
52
|
def Ryo.BasicObject(props, prototype = nil)
|
57
53
|
Ryo::BasicObject.create(props, prototype)
|
58
54
|
end
|
data/lib/ryo/builder.rb
CHANGED
@@ -1,29 +1,21 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# {Ryo::Builder Ryo::Builder}
|
5
|
-
#
|
6
|
-
# {Ryo::BasicObject Ryo::BasicObject}. This module is
|
7
|
-
# used directly.
|
8
|
-
#
|
4
|
+
# The {Ryo::Builder Ryo::Builder} module is responsible for
|
5
|
+
# the creation of instances of {Ryo::Object Ryo::Object},
|
6
|
+
# and {Ryo::BasicObject Ryo::BasicObject}. This module is
|
7
|
+
# not intended to be used directly.
|
9
8
|
# @api private
|
10
9
|
module Ryo::Builder
|
11
10
|
##
|
11
|
+
# @note
|
12
|
+
# When "props" is given as a Ryo object, a duplicate Ryo object is
|
13
|
+
# returned in its place
|
12
14
|
# @param [<Ryo::Object, Ryo::BasicObject>] buildee
|
13
|
-
#
|
14
|
-
#
|
15
|
-
# @param [<Hash, Ryo::Object, Ryo::BasicObject, #each_pair>] props
|
16
|
-
# A Hash object, an object that implements "#each_pair", or a Ryo object.
|
17
|
-
#
|
15
|
+
# @param [<#each_pair>] props
|
18
16
|
# @param [<Ryo::Object, Ryo::BasicObject>, nil] prototype
|
19
|
-
# The prototype, or nil for none.
|
20
|
-
#
|
21
17
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
22
|
-
# Returns a Ryo object
|
23
|
-
#
|
24
|
-
# @note
|
25
|
-
# When "props" is given as a Ryo object, a duplicate Ryo object is
|
26
|
-
# returned in its place.
|
18
|
+
# Returns a Ryo object
|
27
19
|
def self.build(buildee, props, prototype = nil)
|
28
20
|
if Ryo.ryo?(props)
|
29
21
|
build(buildee, Ryo.table_of(props), prototype || Ryo.prototype_of(props))
|
@@ -38,7 +30,8 @@ module Ryo::Builder
|
|
38
30
|
end
|
39
31
|
|
40
32
|
##
|
41
|
-
# Creates a Ryo object by recursively walking a Hash object, or
|
33
|
+
# Creates a Ryo object by recursively walking a Hash object, or
|
34
|
+
# an Array of Hash objects
|
42
35
|
#
|
43
36
|
# @example
|
44
37
|
# objects = Ryo.from([{x: 0, y: 0}, "foo", {point: {x: 0, y: 0}}])
|
@@ -46,22 +39,13 @@ module Ryo::Builder
|
|
46
39
|
# objects[1] # => "foo"
|
47
40
|
# objects[2].point.x # => 0
|
48
41
|
#
|
49
|
-
# @
|
50
|
-
#
|
51
|
-
# @param [<Hash, Ryo::Object, Ryo::BasicObject, Array, #each_pair, #each> ] props
|
52
|
-
# A Hash object, a Ryo object, or an array composed of either Hash / Ryo objects.
|
53
|
-
#
|
54
|
-
# @param prototype (see Ryo::Builder.build)
|
55
|
-
#
|
42
|
+
# @note (see Ryo::Builder.build)
|
43
|
+
# @param (see Ryo::Builder.build)
|
56
44
|
# @return (see Ryo::Builder.build)
|
57
|
-
#
|
58
|
-
# @note
|
59
|
-
# When "props" is given as a Ryo object, a duplicate Ryo object is
|
60
|
-
# returned in its place.
|
61
45
|
def self.recursive_build(buildee, props, prototype = nil)
|
62
46
|
if Ryo.ryo?(props)
|
63
47
|
recursive_build(buildee, Ryo.table_of(props), prototype || Ryo.prototype_of(props))
|
64
|
-
elsif
|
48
|
+
elsif !respond_to_each?(props)
|
65
49
|
raise TypeError, "The provided object does not implement #each / #each_pair"
|
66
50
|
elsif !props.respond_to?(:each_pair)
|
67
51
|
map(props) do
|
@@ -75,32 +59,29 @@ module Ryo::Builder
|
|
75
59
|
end
|
76
60
|
end
|
77
61
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
value
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
62
|
+
module Private
|
63
|
+
private
|
64
|
+
|
65
|
+
def map_value(buildee, value)
|
66
|
+
if Ryo.ryo?(value) || !respond_to_each?(value)
|
67
|
+
value
|
68
|
+
elsif value.respond_to?(:each_pair)
|
69
|
+
recursive_build(buildee, value)
|
70
|
+
elsif value.respond_to?(:each)
|
71
|
+
map(value) { map_value(buildee, _1) }
|
72
|
+
end
|
87
73
|
end
|
88
|
-
end
|
89
|
-
private_class_method :map_value
|
90
74
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
!value.respond_to?(:each) && !value.respond_to?(:each_pair)
|
95
|
-
end
|
96
|
-
private_class_method :eachless?
|
75
|
+
def respond_to_each?(value)
|
76
|
+
value.respond_to?(:each) || value.respond_to?(:each_pair)
|
77
|
+
end
|
97
78
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
ary
|
79
|
+
def map(obj)
|
80
|
+
ary = []
|
81
|
+
obj.each { ary.push(yield(_1)) }
|
82
|
+
ary
|
83
|
+
end
|
104
84
|
end
|
105
|
-
|
85
|
+
private_constant :Private
|
86
|
+
extend Private
|
106
87
|
end
|
data/lib/ryo/enumerable.rb
CHANGED
@@ -1,14 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
##
|
4
|
-
# The {Ryo::Enumerable Ryo::Enumerable} module
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# The {Ryo::Enumerable Ryo::Enumerable} module provides methods
|
5
|
+
# that are similar to Ruby's Enumerable module, and at the same
|
6
|
+
# time - intentionally different.
|
7
|
+
#
|
8
|
+
# For example: {Ryo::Enumerable Ryo::Enumerable}
|
9
|
+
# methods receive 'self' as an argument rather than from the
|
10
|
+
# surrounding context. The methods implemented by this
|
11
|
+
# module are available as singleton methods on the {Ryo Ryo}
|
12
|
+
# module.
|
8
13
|
module Ryo::Enumerable
|
9
14
|
##
|
10
|
-
# The {#each}
|
11
|
-
#
|
15
|
+
# The {#each} method iterates through a Ryo object, and
|
16
|
+
# yields two parameters: a key, and a value
|
12
17
|
#
|
13
18
|
# @example
|
14
19
|
# point_a = Ryo(x: 1, y: 2)
|
@@ -18,23 +23,19 @@ module Ryo::Enumerable
|
|
18
23
|
# # ["y", 2]
|
19
24
|
# # ["x", 1]
|
20
25
|
#
|
21
|
-
# @param
|
22
|
-
# A Ryo object.
|
23
|
-
#
|
24
|
-
# @param ancestors (see #each_ryo)
|
25
|
-
#
|
26
|
+
# @param (see #each_ryo)
|
26
27
|
# @return [<Enumerator, Array>]
|
27
|
-
# Returns an Enumerator when a block is not given, otherwise returns an Array.
|
28
28
|
def each(ryo, ancestors: nil)
|
29
29
|
return enum_for(:each, ryo) unless block_given?
|
30
|
-
each_ryo(ryo, ancestors:
|
30
|
+
each_ryo(ryo, ancestors:) do |_, key, value|
|
31
31
|
yield(key, value)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
##
|
36
|
-
# The {#each_ryo} method iterates through a Ryo object,
|
37
|
-
# {#each_ryo} yields three parameters:
|
36
|
+
# The {#each_ryo} method iterates through a Ryo object,
|
37
|
+
# and its prototypes. {#each_ryo} yields three parameters:
|
38
|
+
# a Ryo object, a key, and a value
|
38
39
|
#
|
39
40
|
# @example
|
40
41
|
# point_a = Ryo(x: 1, y: 2)
|
@@ -45,15 +46,13 @@ module Ryo::Enumerable
|
|
45
46
|
# # [point_a, "y", 2]
|
46
47
|
#
|
47
48
|
# @param [<Ryo::BasicObject, Ryo::Object>] ryo
|
48
|
-
# A Ryo object.
|
49
|
-
#
|
50
49
|
# @param [Integer] ancestors
|
51
|
-
#
|
52
|
-
#
|
53
|
-
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
50
|
+
# "ancestors" is an integer that defines the traversal depth
|
51
|
+
# of a {Ryo::Enumerable Ryo::Enumerable} method. 0 covers a
|
52
|
+
# Ryo object, and none of the prototypes in its prototype
|
53
|
+
# chain. 1 covers a Ryo object, and one of the prototypes
|
54
|
+
# in its prototype chain - and so on. The default covers
|
55
|
+
# the entire prototype chain.
|
57
56
|
# @return [<Ryo::BasicObject, Ryo::Object>]
|
58
57
|
def each_ryo(ryo, ancestors: nil)
|
59
58
|
proto_chain = [ryo, *prototype_chain_of(ryo)]
|
@@ -67,17 +66,19 @@ module Ryo::Enumerable
|
|
67
66
|
end
|
68
67
|
|
69
68
|
##
|
70
|
-
# The {#map} method creates a copy of a Ryo object,
|
71
|
-
# on the copy and
|
69
|
+
# The {#map} method creates a copy of a Ryo object,
|
70
|
+
# and then performs a map operation on the copy and
|
71
|
+
# its prototypes
|
72
72
|
#
|
73
|
-
# @param (see #
|
74
|
-
# @return
|
73
|
+
# @param (see #each_ryo)
|
74
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
75
75
|
def map(ryo, ancestors: nil, &b)
|
76
|
-
map!(Ryo.dup(ryo), ancestors
|
76
|
+
map!(Ryo.dup(ryo), ancestors:, &b)
|
77
77
|
end
|
78
78
|
|
79
79
|
##
|
80
|
-
# The {#map!} method performs an in-place map operation
|
80
|
+
# The {#map!} method performs an in-place map operation
|
81
|
+
# on a Ryo object, and its prototypes
|
81
82
|
#
|
82
83
|
# @example
|
83
84
|
# point = Ryo(x: 2, y: 4)
|
@@ -85,31 +86,28 @@ module Ryo::Enumerable
|
|
85
86
|
# [point.x, point.y]
|
86
87
|
# # => [4, 8]
|
87
88
|
#
|
88
|
-
# @param
|
89
|
-
# A Ryo object.
|
90
|
-
#
|
91
|
-
# @param ancestors (see #each_ryo)
|
92
|
-
#
|
89
|
+
# @param (see #each_ryo)
|
93
90
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
94
91
|
def map!(ryo, ancestors: nil)
|
95
|
-
each_ryo(ryo, ancestors:
|
92
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
96
93
|
ryo[key] = yield(key, value)
|
97
94
|
end
|
98
95
|
end
|
99
96
|
|
100
97
|
##
|
101
|
-
# The {#select} method creates a copy of a Ryo object, and
|
102
|
-
# on the copy and its
|
98
|
+
# The {#select} method creates a copy of a Ryo object, and
|
99
|
+
# then performs a filter operation on the copy and its
|
100
|
+
# prototypes
|
103
101
|
#
|
104
|
-
# @param (see #
|
105
|
-
# @return
|
102
|
+
# @param (see #each_ryo)
|
103
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
106
104
|
def select(ryo, ancestors: nil, &b)
|
107
|
-
select!(Ryo.dup(ryo), ancestors
|
105
|
+
select!(Ryo.dup(ryo), ancestors:, &b)
|
108
106
|
end
|
109
107
|
|
110
108
|
##
|
111
|
-
# The {#select!} method performs an in-place filter operation
|
112
|
-
# its prototypes
|
109
|
+
# The {#select!} method performs an in-place filter operation
|
110
|
+
# on a Ryo object, and its prototypes
|
113
111
|
#
|
114
112
|
# @example
|
115
113
|
# point_a = Ryo(x: 1, y: 2, z: 3)
|
@@ -118,31 +116,27 @@ module Ryo::Enumerable
|
|
118
116
|
# [point_b.x, point_b.y, point_b.z]
|
119
117
|
# # => [1, 2, nil]
|
120
118
|
#
|
121
|
-
# @param
|
122
|
-
# A Ryo object.
|
123
|
-
#
|
124
|
-
# @param ancestors (see #each_ryo)
|
125
|
-
#
|
119
|
+
# @param (see #each_ryo)
|
126
120
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
127
121
|
def select!(ryo, ancestors: nil)
|
128
|
-
each_ryo(ryo, ancestors:
|
122
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
129
123
|
delete(ryo, key) unless yield(key, value)
|
130
124
|
end
|
131
125
|
end
|
132
126
|
|
133
127
|
##
|
134
|
-
# The {#reject} method creates a copy of a Ryo object, and then
|
135
|
-
# on the copy and its prototypes
|
128
|
+
# The {#reject} method creates a copy of a Ryo object, and then
|
129
|
+
# performs a filter operation on the copy and its prototypes
|
136
130
|
#
|
137
|
-
# @param (see #
|
138
|
-
# @return
|
131
|
+
# @param (see #each_ryo)
|
132
|
+
# @return [<Ryo::Object, Ryo::BasicObject>]
|
139
133
|
def reject(ryo, ancestors: nil, &b)
|
140
|
-
reject!(Ryo.dup(ryo), ancestors
|
134
|
+
reject!(Ryo.dup(ryo), ancestors:, &b)
|
141
135
|
end
|
142
136
|
|
143
137
|
##
|
144
|
-
# The {#reject!} method performs an in-place filter operation
|
145
|
-
# its prototypes
|
138
|
+
# The {#reject!} method performs an in-place filter operation
|
139
|
+
# on a Ryo object, and its prototypes
|
146
140
|
#
|
147
141
|
# @example
|
148
142
|
# point_a = Ryo(x: 1, y: 2, z: 3)
|
@@ -151,51 +145,39 @@ module Ryo::Enumerable
|
|
151
145
|
# [point_b.x, point_b.y, point_b.z]
|
152
146
|
# # => [1, 2, nil]
|
153
147
|
#
|
154
|
-
# @param
|
155
|
-
# A Ryo object.
|
156
|
-
#
|
157
|
-
# @param ancestors (see #each_ryo)
|
158
|
-
#
|
148
|
+
# @param (see #each_ryo)
|
159
149
|
# @return [<Ryo::Object, Ryo::BasicObject>]
|
160
150
|
def reject!(ryo, ancestors: nil)
|
161
|
-
each_ryo(ryo, ancestors:
|
151
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
162
152
|
delete(ryo, key) if yield(key, value)
|
163
153
|
end
|
164
154
|
end
|
165
155
|
|
166
156
|
##
|
167
|
-
#
|
168
|
-
# key / value pair to a block. If the block ever returns a truthy value, {#any?} will
|
169
|
-
# break from the iteration and return true - otherwise false will be returned.
|
170
|
-
#
|
171
|
-
# @param ancestors (see #each_ryo)
|
157
|
+
# @param (see #each_ryo)
|
172
158
|
# @return [Boolean]
|
159
|
+
# Returns true when the given block evaluates to
|
160
|
+
# a truthy value for at least one iteration
|
173
161
|
def any?(ryo, ancestors: nil)
|
174
|
-
each_ryo(ryo, ancestors:
|
162
|
+
each_ryo(ryo, ancestors:) do |_, key, value|
|
175
163
|
return true if yield(key, value)
|
176
164
|
end
|
177
165
|
false
|
178
166
|
end
|
179
167
|
|
180
168
|
##
|
181
|
-
#
|
182
|
-
# key / value pair to a block. If the block ever returns a falsey value, {#all?} will
|
183
|
-
# break from the iteration and return false - otherwise true will be returned.
|
184
|
-
#
|
185
|
-
# @param ancestors (see #each_ryo)
|
169
|
+
# @param (see #each_ryo)
|
186
170
|
# @return [Boolean]
|
171
|
+
# Returns true when the given block evaluates to a
|
172
|
+
# truthy value for every iteration
|
187
173
|
def all?(ryo, ancestors: nil)
|
188
|
-
each_ryo(ryo, ancestors:
|
174
|
+
each_ryo(ryo, ancestors:) do |_, key, value|
|
189
175
|
return false unless yield(key, value)
|
190
176
|
end
|
191
177
|
true
|
192
178
|
end
|
193
179
|
|
194
180
|
##
|
195
|
-
# The {#find} method iterates through a Ryo object, and its prototypes - yielding a
|
196
|
-
# key / value pair to a block. If the block ever returns a truthy value, {#find} will
|
197
|
-
# break from the iteration and return a Ryo object - otherwise nil will be returned.
|
198
|
-
#
|
199
181
|
# @example
|
200
182
|
# point_a = Ryo(x: 5)
|
201
183
|
# point_b = Ryo({y: 10}, point_a)
|
@@ -203,10 +185,11 @@ module Ryo::Enumerable
|
|
203
185
|
# ryo = Ryo.find(point_c) { |key, value| value == 5 }
|
204
186
|
# ryo == point_a # => true
|
205
187
|
#
|
206
|
-
# @param
|
188
|
+
# @param (see #each_ryo)
|
207
189
|
# @return [<Ryo::Object, Ryo::BasicObject>, nil]
|
190
|
+
# Returns a Ryo object, or nil
|
208
191
|
def find(ryo, ancestors: nil)
|
209
|
-
each_ryo(ryo, ancestors:
|
192
|
+
each_ryo(ryo, ancestors:) do |ryo, key, value|
|
210
193
|
return ryo if yield(key, value)
|
211
194
|
end
|
212
195
|
nil
|
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
|