ryo.rb 0.5.3 → 0.5.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|