ashikawa-core 0.7.2 → 0.8.0
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 +7 -0
- data/.coveralls.yml +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +0 -4
- data/Gemfile +1 -1
- data/Gemfile.devtools +24 -18
- data/README.md +6 -11
- data/ashikawa-core.gemspec +7 -6
- data/config/flay.yml +2 -2
- data/config/flog.yml +2 -1
- data/config/reek.yml +68 -84
- data/config/rubocop.yml +99 -0
- data/config/yardstick.yml +1 -1
- data/lib/ashikawa-core/collection.rb +74 -21
- data/lib/ashikawa-core/configuration.rb +26 -0
- data/lib/ashikawa-core/connection.rb +5 -2
- data/lib/ashikawa-core/cursor.rb +28 -16
- data/lib/ashikawa-core/database.rb +89 -12
- data/lib/ashikawa-core/document.rb +32 -5
- data/lib/ashikawa-core/edge.rb +3 -0
- data/lib/ashikawa-core/exceptions/client_error.rb +3 -3
- data/lib/ashikawa-core/exceptions/server_error.rb +3 -3
- data/lib/ashikawa-core/figure.rb +17 -5
- data/lib/ashikawa-core/index.rb +4 -0
- data/lib/ashikawa-core/key_options.rb +54 -0
- data/lib/ashikawa-core/query.rb +39 -74
- data/lib/ashikawa-core/request_preprocessor.rb +2 -2
- data/lib/ashikawa-core/response_preprocessor.rb +21 -12
- data/lib/ashikawa-core/transaction.rb +113 -0
- data/lib/ashikawa-core/version.rb +1 -1
- data/spec/acceptance/basic_spec.rb +40 -12
- data/spec/acceptance/index_spec.rb +2 -1
- data/spec/acceptance/query_spec.rb +18 -17
- data/spec/acceptance/transactions_spec.rb +30 -0
- data/spec/fixtures/collections/all.json +90 -30
- data/spec/fixtures/cursor/edges.json +23 -0
- data/spec/setup/arangodb.sh +7 -6
- data/spec/unit/collection_spec.rb +89 -13
- data/spec/unit/connection_spec.rb +23 -14
- data/spec/unit/cursor_spec.rb +15 -4
- data/spec/unit/database_spec.rb +58 -17
- data/spec/unit/document_spec.rb +24 -4
- data/spec/unit/edge_spec.rb +1 -1
- data/spec/unit/exception_spec.rb +4 -2
- data/spec/unit/figure_spec.rb +17 -10
- data/spec/unit/index_spec.rb +1 -1
- data/spec/unit/key_options_spec.rb +25 -0
- data/spec/unit/query_spec.rb +1 -1
- data/spec/unit/spec_helper.rb +20 -2
- data/spec/unit/transaction_spec.rb +153 -0
- data/tasks/adjustments.rake +23 -14
- metadata +31 -41
- data/.rvmrc +0 -1
- data/config/roodi.yml +0 -17
- data/spec/spec_helper.rb +0 -27
data/config/yardstick.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 100
|
@@ -5,7 +5,9 @@ require "ashikawa-core/cursor"
|
|
5
5
|
require "ashikawa-core/query"
|
6
6
|
require "ashikawa-core/status"
|
7
7
|
require "ashikawa-core/figure"
|
8
|
+
require "ashikawa-core/key_options"
|
8
9
|
require "forwardable"
|
10
|
+
require "equalizer"
|
9
11
|
|
10
12
|
module Ashikawa
|
11
13
|
module Core
|
@@ -13,6 +15,8 @@ module Ashikawa
|
|
13
15
|
class Collection
|
14
16
|
extend Forwardable
|
15
17
|
|
18
|
+
include Equalizer.new(:id, :name, :content_type, :database)
|
19
|
+
|
16
20
|
CONTENT_TYPES = {
|
17
21
|
2 => :document,
|
18
22
|
3 => :edge
|
@@ -205,6 +209,17 @@ module Ashikawa
|
|
205
209
|
send_information_to_server(:properties, :waitForSync, new_value)
|
206
210
|
end
|
207
211
|
|
212
|
+
# Get information about the type of keys of this collection
|
213
|
+
#
|
214
|
+
# @return [KeyOptions]
|
215
|
+
# @api public
|
216
|
+
# @example Check if this collection has autoincrementing keys
|
217
|
+
# collection = Ashikawa::Core::Collection.new(database, raw_collection)
|
218
|
+
# collection.key_options.type # => "autoincrement"
|
219
|
+
def key_options
|
220
|
+
KeyOptions.new(get_information_from_server(:properties, :keyOptions))
|
221
|
+
end
|
222
|
+
|
208
223
|
# Returns the number of documents in the collection
|
209
224
|
#
|
210
225
|
# @return [Fixnum] Number of documents
|
@@ -326,29 +341,56 @@ module Ashikawa
|
|
326
341
|
send_command_to_server(:truncate)
|
327
342
|
end
|
328
343
|
|
329
|
-
# Fetch a certain document by its
|
344
|
+
# Fetch a certain document by its key
|
330
345
|
#
|
331
|
-
# @param [Integer]
|
346
|
+
# @param [Integer] document_key the key of the document
|
332
347
|
# @raise [DocumentNotFoundException] If the requested document was not found
|
333
348
|
# @return Document
|
334
349
|
# @api public
|
335
|
-
# @example Fetch the document with the
|
336
|
-
# document = collection
|
337
|
-
def
|
338
|
-
response =
|
350
|
+
# @example Fetch the document with the key 12345
|
351
|
+
# document = collection.fetch(12345)
|
352
|
+
def fetch(document_key)
|
353
|
+
response = send_request_for_content_key(document_key)
|
339
354
|
@content_class.new(@database, response)
|
340
355
|
end
|
341
356
|
|
342
|
-
#
|
357
|
+
# Fetch a certain document by its key, return nil if the document does not exist
|
343
358
|
#
|
344
|
-
# @param [Integer]
|
359
|
+
# @param [Integer] document_key the id of the document
|
360
|
+
# @return Document
|
361
|
+
# @api public
|
362
|
+
# @example Fetch the document with the key 12345
|
363
|
+
# document = collection[12345]
|
364
|
+
def [](document_key)
|
365
|
+
fetch(document_key)
|
366
|
+
rescue DocumentNotFoundException
|
367
|
+
nil
|
368
|
+
end
|
369
|
+
|
370
|
+
# Replace a document by its key
|
371
|
+
#
|
372
|
+
# @param [Integer] document_key the key of the document
|
345
373
|
# @param [Hash] raw_document the data you want to replace it with
|
346
374
|
# @return [Hash] parsed JSON response from the server
|
347
375
|
# @api public
|
348
|
-
# @example Replace the document with the
|
349
|
-
# collection
|
350
|
-
def
|
351
|
-
|
376
|
+
# @example Replace the document with the key 12345
|
377
|
+
# collection.replace(12345, document)
|
378
|
+
def replace(document_key, raw_document)
|
379
|
+
send_request_for_content_key(document_key, :put => raw_document)
|
380
|
+
end
|
381
|
+
|
382
|
+
# Replace a document by its key
|
383
|
+
#
|
384
|
+
# @param [Integer] document_key the key of the document
|
385
|
+
# @param [Hash] raw_document the data you want to replace it with
|
386
|
+
# @return [Hash] parsed JSON response from the server
|
387
|
+
# @api public
|
388
|
+
# @deprecated Use {#replace} instead.
|
389
|
+
# @example Replace the document with the key 12345
|
390
|
+
# collection.replace(12345, document)
|
391
|
+
def []=(document_key, raw_document)
|
392
|
+
warn "`[]=` is deprecated, please use `replace`"
|
393
|
+
replace(document_key, raw_document)
|
352
394
|
end
|
353
395
|
|
354
396
|
# Create a new document with given attributes
|
@@ -361,10 +403,21 @@ module Ashikawa
|
|
361
403
|
def create_document(attributes)
|
362
404
|
raise "Can't create a document in an edge collection" if @content_type == :edge
|
363
405
|
response = send_request_for_content(:post => attributes)
|
364
|
-
Document.new(@database, response)
|
406
|
+
Document.new(@database, response).refresh!
|
365
407
|
end
|
366
408
|
|
367
|
-
|
409
|
+
# Create a new document with given attributes
|
410
|
+
#
|
411
|
+
# @param [Hash] attributes
|
412
|
+
# @return [Document] The created document
|
413
|
+
# @api public
|
414
|
+
# @deprecated Use {#create_document} instead.
|
415
|
+
# @example Create a new document from raw data
|
416
|
+
# collection << attributes
|
417
|
+
def <<(attributes)
|
418
|
+
warn "`<<` is deprecated, please use `create_document`"
|
419
|
+
create_document(attributes)
|
420
|
+
end
|
368
421
|
|
369
422
|
# Create a new edge between two documents with certain attributes
|
370
423
|
#
|
@@ -378,7 +431,7 @@ module Ashikawa
|
|
378
431
|
def create_edge(from, to, attributes)
|
379
432
|
raise "Can't create an edge in a document collection" if @content_type == :document
|
380
433
|
response = send_request("edge?collection=#{@id}&from=#{from.id}&to=#{to.id}", :post => attributes)
|
381
|
-
Edge.new(@database, response)
|
434
|
+
Edge.new(@database, response).refresh!
|
382
435
|
end
|
383
436
|
|
384
437
|
# Add an index to the collection
|
@@ -408,8 +461,8 @@ module Ashikawa
|
|
408
461
|
# people = database['people']
|
409
462
|
# people.index(1244) #=> #<Index: id=1244...>
|
410
463
|
def index(id)
|
411
|
-
|
412
|
-
Index.new(self,
|
464
|
+
response = send_request("index/#{@name}/#{id}")
|
465
|
+
Index.new(self, response)
|
413
466
|
end
|
414
467
|
|
415
468
|
# Get all indices
|
@@ -486,7 +539,7 @@ module Ashikawa
|
|
486
539
|
#
|
487
540
|
# @return [String] Response from the server
|
488
541
|
# @api private
|
489
|
-
def send_request_for_this_collection(path, method={})
|
542
|
+
def send_request_for_this_collection(path, method = {})
|
490
543
|
send_request("collection/#{id}/#{path}", method)
|
491
544
|
end
|
492
545
|
|
@@ -503,14 +556,14 @@ module Ashikawa
|
|
503
556
|
self
|
504
557
|
end
|
505
558
|
|
506
|
-
# Send a request for the content with the given
|
559
|
+
# Send a request for the content with the given key
|
507
560
|
#
|
508
561
|
# @param [Integer] document_id The id of the document
|
509
562
|
# @param [Hash] opts The options for the request
|
510
563
|
# @return [Hash] parsed JSON response from the server
|
511
564
|
# @api private
|
512
|
-
def
|
513
|
-
send_request("#{@content_type}/#{@id}/#{
|
565
|
+
def send_request_for_content_key(document_key, opts = {})
|
566
|
+
send_request("#{@content_type}/#{@id}/#{document_key}", opts)
|
514
567
|
end
|
515
568
|
|
516
569
|
# Send a request for the content of this collection
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Ashikawa
|
2
|
+
module Core
|
3
|
+
# Configuration of Ashikawa::Core
|
4
|
+
class Configuration < Struct.new(:url, :connection, :logger, :adapter)
|
5
|
+
# The URL of the database instance
|
6
|
+
# @api private
|
7
|
+
# @return String
|
8
|
+
attr_accessor :url
|
9
|
+
|
10
|
+
# The Connection object
|
11
|
+
# @api private
|
12
|
+
# @return Connection
|
13
|
+
attr_accessor :connection
|
14
|
+
|
15
|
+
# The logger instance
|
16
|
+
# @api private
|
17
|
+
# @return Object
|
18
|
+
attr_accessor :logger
|
19
|
+
|
20
|
+
# The HTTP adapter instance
|
21
|
+
# @api private
|
22
|
+
# @return Object
|
23
|
+
attr_accessor :adapter
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -2,6 +2,7 @@ require "forwardable"
|
|
2
2
|
require "faraday"
|
3
3
|
require "null_logger"
|
4
4
|
require "uri"
|
5
|
+
require "equalizer"
|
5
6
|
require "ashikawa-core/request_preprocessor"
|
6
7
|
require "ashikawa-core/response_preprocessor"
|
7
8
|
|
@@ -11,6 +12,8 @@ module Ashikawa
|
|
11
12
|
class Connection
|
12
13
|
extend Forwardable
|
13
14
|
|
15
|
+
include Equalizer.new(:host, :scheme, :port)
|
16
|
+
|
14
17
|
# The host part of the connection
|
15
18
|
#
|
16
19
|
# @!method host
|
@@ -55,7 +58,7 @@ module Ashikawa
|
|
55
58
|
@connection = Faraday.new("#{api_string}/_api") do |connection|
|
56
59
|
connection.request :ashikawa_request, logger
|
57
60
|
connection.response :ashikawa_response, logger
|
58
|
-
connection.adapter
|
61
|
+
connection.adapter(*adapter)
|
59
62
|
end
|
60
63
|
end
|
61
64
|
|
@@ -113,7 +116,7 @@ module Ashikawa
|
|
113
116
|
# @return [Symbol] The HTTP verb used
|
114
117
|
# @api private
|
115
118
|
def http_verb(params)
|
116
|
-
[:post, :put, :delete].
|
119
|
+
[:post, :put, :delete].detect { |method_name|
|
117
120
|
params.has_key?(method_name)
|
118
121
|
} || :get
|
119
122
|
end
|
data/lib/ashikawa-core/cursor.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
require 'ashikawa-core/document'
|
2
|
+
require 'ashikawa-core/edge'
|
3
|
+
require 'equalizer'
|
2
4
|
|
3
5
|
module Ashikawa
|
4
6
|
module Core
|
@@ -7,6 +9,8 @@ module Ashikawa
|
|
7
9
|
class Cursor
|
8
10
|
include Enumerable
|
9
11
|
|
12
|
+
include Equalizer.new(:id)
|
13
|
+
|
10
14
|
# The ID of the cursor
|
11
15
|
# @return [String]
|
12
16
|
# @api public
|
@@ -54,7 +58,7 @@ module Ashikawa
|
|
54
58
|
|
55
59
|
begin
|
56
60
|
@current.each do |raw_document|
|
57
|
-
yield
|
61
|
+
yield parse_raw_document(raw_document)
|
58
62
|
end
|
59
63
|
end while next_batch
|
60
64
|
nil
|
@@ -72,6 +76,28 @@ module Ashikawa
|
|
72
76
|
|
73
77
|
private
|
74
78
|
|
79
|
+
# Parse a raw document and return a Document or Edge for it
|
80
|
+
#
|
81
|
+
# @param [Hash] raw_document
|
82
|
+
# @return Document | Edge
|
83
|
+
# @api private
|
84
|
+
def parse_raw_document(raw_document)
|
85
|
+
detect_document_class_for(raw_document).new(@database, raw_document)
|
86
|
+
end
|
87
|
+
|
88
|
+
# Detect if a raw document is a document or edge and return the class
|
89
|
+
#
|
90
|
+
# @param [Hash] raw_document
|
91
|
+
# @return class
|
92
|
+
# @api private
|
93
|
+
def detect_document_class_for(raw_document)
|
94
|
+
if raw_document.has_key?("_from") && raw_document.has_key?("_to")
|
95
|
+
Edge
|
96
|
+
else
|
97
|
+
Document
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
75
101
|
# Pull the raw data from the cursor into this object
|
76
102
|
#
|
77
103
|
# @param [Hash] raw_cursor
|
@@ -80,11 +106,7 @@ module Ashikawa
|
|
80
106
|
def parse_raw_cursor(raw_cursor)
|
81
107
|
@id = raw_cursor['id']
|
82
108
|
@has_more = raw_cursor['hasMore']
|
83
|
-
|
84
|
-
parse_documents_cursor(raw_cursor)
|
85
|
-
elsif raw_cursor['document']
|
86
|
-
parse_document_cursor(raw_cursor)
|
87
|
-
end
|
109
|
+
parse_documents_cursor(raw_cursor)
|
88
110
|
self
|
89
111
|
end
|
90
112
|
|
@@ -98,16 +120,6 @@ module Ashikawa
|
|
98
120
|
@length = raw_cursor['count'].to_i if raw_cursor.has_key?('count')
|
99
121
|
end
|
100
122
|
|
101
|
-
# Parse the cursor for a single document
|
102
|
-
#
|
103
|
-
# @param [Hash] raw_cursor
|
104
|
-
# @return self
|
105
|
-
# @api private
|
106
|
-
def parse_document_cursor(raw_cursor)
|
107
|
-
@current = [raw_cursor['document']]
|
108
|
-
@length = 1
|
109
|
-
end
|
110
|
-
|
111
123
|
# Get a new batch from the server
|
112
124
|
#
|
113
125
|
# @return [Boolean] Is there a next batch?
|
@@ -2,13 +2,13 @@ require "ashikawa-core/exceptions/client_error/resource_not_found/collection_not
|
|
2
2
|
require "ashikawa-core/collection"
|
3
3
|
require "ashikawa-core/connection"
|
4
4
|
require "ashikawa-core/cursor"
|
5
|
+
require "ashikawa-core/configuration"
|
6
|
+
require "ashikawa-core/transaction"
|
5
7
|
require "forwardable"
|
8
|
+
require "equalizer"
|
6
9
|
|
7
10
|
module Ashikawa
|
8
11
|
module Core
|
9
|
-
# Configuration of Ashikawa::Core
|
10
|
-
Configuration = Struct.new(:url, :connection, :logger, :adapter)
|
11
|
-
|
12
12
|
# An ArangoDB database
|
13
13
|
class Database
|
14
14
|
COLLECTION_TYPES = {
|
@@ -18,6 +18,8 @@ module Ashikawa
|
|
18
18
|
|
19
19
|
extend Forwardable
|
20
20
|
|
21
|
+
include Equalizer.new(:host, :port, :scheme)
|
22
|
+
|
21
23
|
# Delegate sending requests to the connection
|
22
24
|
def_delegator :@connection, :send_request
|
23
25
|
def_delegator :@connection, :host
|
@@ -43,13 +45,13 @@ module Ashikawa
|
|
43
45
|
# config.adapter = my_adapter
|
44
46
|
# config.logger = my_logger
|
45
47
|
# end
|
46
|
-
def initialize
|
48
|
+
def initialize
|
47
49
|
configuration = Ashikawa::Core::Configuration.new
|
48
50
|
yield(configuration)
|
49
51
|
@connection = configuration.connection || setup_new_connection(configuration.url, configuration.logger, configuration.adapter)
|
50
52
|
end
|
51
53
|
|
52
|
-
# Returns a list of all collections defined in the database
|
54
|
+
# Returns a list of all non-system collections defined in the database
|
53
55
|
#
|
54
56
|
# @return [Array<Collection>]
|
55
57
|
# @api public
|
@@ -59,8 +61,18 @@ module Ashikawa
|
|
59
61
|
# database["b"]
|
60
62
|
# database.collections # => [ #<Collection name="a">, #<Collection name="b">]
|
61
63
|
def collections
|
62
|
-
|
63
|
-
|
64
|
+
all_collections_where { |collection| !collection["name"].start_with?("_") }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Returns a list of all system collections defined in the database
|
68
|
+
#
|
69
|
+
# @return [Array<Collection>]
|
70
|
+
# @api public
|
71
|
+
# @example Get an Array containing the Collections in the database
|
72
|
+
# database = Ashikawa::Core::Database.new("http://localhost:8529")
|
73
|
+
# database.system_collections # => [ #<Collection name="_a">, #<Collection name="_b">]
|
74
|
+
def system_collections
|
75
|
+
all_collections_where { |collection| collection["name"].start_with?("_") }
|
64
76
|
end
|
65
77
|
|
66
78
|
# Create a Collection based on name
|
@@ -73,11 +85,8 @@ module Ashikawa
|
|
73
85
|
# @example Create a new, volatile collection
|
74
86
|
# database = Ashikawa::Core::Database.new("http://localhost:8529")
|
75
87
|
# database.create_collection("a", :isVolatile => true) # => #<Collection name="a">
|
76
|
-
def create_collection(collection_identifier, opts={})
|
77
|
-
|
78
|
-
params[:isVolatile] = true if opts[:is_volatile] == true
|
79
|
-
params[:type] = COLLECTION_TYPES[opts[:content_type]] if opts.has_key?(:content_type)
|
80
|
-
response = send_request("collection", :post => params)
|
88
|
+
def create_collection(collection_identifier, opts = {})
|
89
|
+
response = send_request("collection", :post => translate_params(collection_identifier, opts))
|
81
90
|
Ashikawa::Core::Collection.new(self, response)
|
82
91
|
end
|
83
92
|
|
@@ -115,6 +124,22 @@ module Ashikawa
|
|
115
124
|
Query.new(self)
|
116
125
|
end
|
117
126
|
|
127
|
+
# Create a new Transaction for this database
|
128
|
+
#
|
129
|
+
# @param [String] action The JS action you want to execute
|
130
|
+
# @options collections [Array<String>] :read The collections you want to read from
|
131
|
+
# @options collections [Array<String>] :write The collections you want to write to
|
132
|
+
# @return [Object] The result of the transaction
|
133
|
+
# @api public
|
134
|
+
# @example Create a new Transaction
|
135
|
+
# transaction = database.create_transaction("function () { return 5; }", :read => ["collection_1"])
|
136
|
+
# transaction.execute #=> 5
|
137
|
+
def create_transaction(action, collections)
|
138
|
+
Ashikawa::Core::Transaction.new(self, action, collections)
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
118
143
|
# Setup the connection object
|
119
144
|
#
|
120
145
|
# @param [String] url
|
@@ -129,6 +154,58 @@ module Ashikawa
|
|
129
154
|
:adapter => adapter
|
130
155
|
})
|
131
156
|
end
|
157
|
+
|
158
|
+
# Parse a raw collection
|
159
|
+
#
|
160
|
+
# @param [Array] raw_collections
|
161
|
+
# @return [Array]
|
162
|
+
# @api private
|
163
|
+
def parse_raw_collections(raw_collections)
|
164
|
+
raw_collections.map { |collection|
|
165
|
+
Ashikawa::Core::Collection.new(self, collection)
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
# Translate the key options into the required format
|
170
|
+
#
|
171
|
+
# @param [Hash] key_options
|
172
|
+
# @return [Hash]
|
173
|
+
# @api private
|
174
|
+
def translate_key_options(key_options)
|
175
|
+
{
|
176
|
+
:type => key_options[:type].to_s,
|
177
|
+
:offset => key_options[:offset],
|
178
|
+
:increment => key_options[:increment],
|
179
|
+
:allowUserKeys => key_options[:allow_user_keys]
|
180
|
+
}
|
181
|
+
end
|
182
|
+
|
183
|
+
# Translate the params into the required format
|
184
|
+
#
|
185
|
+
# @param [String] collection_identifier
|
186
|
+
# @param [Hash] opts
|
187
|
+
# @return [Hash]
|
188
|
+
# @api private
|
189
|
+
def translate_params(collection_identifier, opts)
|
190
|
+
params = { :name => collection_identifier }
|
191
|
+
params[:isVolatile] = true if opts[:is_volatile] == true
|
192
|
+
params[:type] = COLLECTION_TYPES[opts[:content_type]] if opts.has_key?(:content_type)
|
193
|
+
params[:keyOptions] = translate_key_options(opts[:key_options]) if opts.has_key?(:key_options)
|
194
|
+
params
|
195
|
+
end
|
196
|
+
|
197
|
+
# Get all collections that fulfill a certain criteria
|
198
|
+
#
|
199
|
+
# @yield [raw_collection] Yields the raw collections so you can decide which to keep
|
200
|
+
# @yieldparam [raw_collection] A raw collection
|
201
|
+
# @yieldreturn [Boolean] Should the collection be kept
|
202
|
+
# @return [Array<Collection>]
|
203
|
+
# @api private
|
204
|
+
def all_collections_where(&block)
|
205
|
+
raw_collections = send_request("collection")["collections"]
|
206
|
+
raw_collections.keep_if(&block)
|
207
|
+
parse_raw_collections(raw_collections)
|
208
|
+
end
|
132
209
|
end
|
133
210
|
end
|
134
211
|
end
|