Class: Parse::CollectionProxy

Inherits:
Object
  • Object
show all
Includes:
ActiveModel::Dirty, ActiveModel::Model, Enumerable
Defined in:
lib/parse/model/associations/collection_proxy.rb

Overview

A CollectionProxy is a special type of array wrapper that notifies a delegate object about changes to the array in order to perform dirty tracking. This is used for all Array properties in Parse::Objects. Subclasses of CollectionProxy are also available for supporting different association types such as an array of Parse pointers and Parse relations.

Direct Known Subclasses

PointerCollectionProxy

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(collection = nil, delegate: nil, key: nil, parse_class: nil) ⇒ CollectionProxy

Create a new CollectionProxy instance.

Parameters:

  • collection (Array) (defaults to: nil)

    the initial items to add to the collection.

  • delegate (Object) (defaults to: nil)

    the owner of the object that will receive the notifications.

  • key (Symbol) (defaults to: nil)

    the name of the key to use when sending notifications for _will_change! and _fetch!

  • parse_class (String) (defaults to: nil)

    (Optional) the Parse class type are the items of the collection. This is used to typecast the objects in the array to a particular Parse Object type.

See Also:



62
63
64
65
66
67
68
# File 'lib/parse/model/associations/collection_proxy.rb', line 62

def initialize(collection = nil, delegate: nil, key: nil, parse_class: nil)
  @delegate = delegate
  @key = key.to_sym if key.present?
  @collection = collection.is_a?(Array) ? collection : []
  @loaded = @collection.count > 0
  @parse_class = parse_class
end

Instance Attribute Details

#collectionArray

Note:

If you modify this directly, it is highly recommended that you call #notify_will_change! to notify the dirty tracking system.

Returns contents of the collection.

Returns:

  • (Array)

    contents of the collection.



130
131
132
133
134
135
136
137
# File 'lib/parse/model/associations/collection_proxy.rb', line 130

def collection
  if @collection.empty? && @loaded == false
    @collection = forward(:"#{@key}_fetch!") || @collection || []
    @loaded = true
  end

  @collection
end

#delegateObject (readonly)

The object to be notified of changes to the collection.

Returns:



# File 'lib/parse/model/associations/collection_proxy.rb', line 31

#keyString (readonly)

the name of the property key to use when sending notifications for _will_change! and _fetch!

Returns:



# File 'lib/parse/model/associations/collection_proxy.rb', line 42

#loadedObject

The writer for :collection is defined explicitly below with dirty-tracking notification; do not declare attr_writer :collection here.



# File 'lib/parse/model/associations/collection_proxy.rb', line 35

#parse_classObject

The writer for :collection is defined explicitly below with dirty-tracking notification; do not declare attr_writer :collection here.



# File 'lib/parse/model/associations/collection_proxy.rb', line 38

Instance Method Details

#&(other_ary) ⇒ Array

Set Intersection - Returns a new array containing unique elements common to the two arrays. The order is preserved from the original array.

It compares elements using their hash and eql? methods for efficiency. See Array#&

Examples:

[ 1, 1, 3, 5 ] & [ 3, 2, 1 ]                 #=> [ 1, 3 ]
[ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ]   #=> [ 'a', 'b' ]

Parameters:

Returns:

  • (Array)

    intersection array



191
192
193
# File 'lib/parse/model/associations/collection_proxy.rb', line 191

def &(other_ary)
  collection & [other_ary].flatten
end

#+(other_ary) ⇒ Array

Alias Array Concatenation. Returns a new array built by concatenating the two arrays together to produce a third array.

Examples:

[ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]

Parameters:

Returns:

  • (Array)

    concatenated array



214
215
216
# File 'lib/parse/model/associations/collection_proxy.rb', line 214

def +(other_ary)
  collection + [other_ary].flatten.to_a
end

#-(other_ary) ⇒ Array

Alias Array Difference. Returns a new array that is a copy of the original array, removing any items that also appear in other_ary. The order is preserved from the original array.

Examples:

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]

Parameters:

Returns:

  • (Array)

    delta array



203
204
205
# File 'lib/parse/model/associations/collection_proxy.rb', line 203

def -(other_ary)
  collection - [other_ary].flatten
end

#<<(*list) ⇒ Object

Append items to the collection



353
354
355
356
357
358
# File 'lib/parse/model/associations/collection_proxy.rb', line 353

def <<(*list)
  if list.count > 0
    notify_will_change!
    list.flatten.each { |e| collection.push(e) }
  end
end

#==(other_list) ⇒ Boolean

Returns true if two collection proxies have similar items.

Returns:

  • (Boolean)

    true if two collection proxies have similar items.



91
92
93
94
95
96
97
# File 'lib/parse/model/associations/collection_proxy.rb', line 91

def ==(other_list)
  if other_list.is_a?(Array)
    return @collection == other_list
  elsif other_list.is_a?(Parse::CollectionProxy)
    return @collection == other_list.instance_variable_get(:@collection)
  end
end

#add(*items) ⇒ Object Also known as: push

Add items to the collection

Parameters:

  • items (Array)

    items to add



146
147
148
149
150
151
152
# File 'lib/parse/model/associations/collection_proxy.rb', line 146

def add(*items)
  notify_will_change! if items.count > 0
  items.each do |item|
    collection.push item
  end
  @collection
end

#add!(*items) ⇒ Object

Note:

Parse objects are automatically converted to pointer format

Atomically adds all items from the array. This request is sent directly to the Parse backend.

Parameters:

  • items (Array)

    items to uniquely add

See Also:



241
242
243
244
245
# File 'lib/parse/model/associations/collection_proxy.rb', line 241

def add!(*items)
  return false unless @delegate.respond_to?(:op_add!)
  @delegate.send :op_add!, @key, items_to_pointers(items.flatten)
  reset!
end

#add_unique(*items) ⇒ Array Also known as: push_unique

Add items to the collection if they don’t already exist

Parameters:

  • items (Array)

    items to uniquely add

Returns:

  • (Array)

    the collection.



159
160
161
162
163
164
# File 'lib/parse/model/associations/collection_proxy.rb', line 159

def add_unique(*items)
  return unless items.count > 0
  notify_will_change!
  @collection = collection | items.flatten
  @collection
end

#add_unique!(*items) ⇒ Object

Note:

Parse objects are automatically converted to pointer format

Atomically adds all items from the array that are not already part of the collection. This request is sent directly to the Parse backend.

Parameters:

  • items (Array)

    items to uniquely add

See Also:



252
253
254
255
256
# File 'lib/parse/model/associations/collection_proxy.rb', line 252

def add_unique!(*items)
  return false unless @delegate.respond_to?(:op_add_unique!)
  @delegate.send :op_add_unique!, @key, items_to_pointers(items.flatten)
  reset!
end

#as_json(opts = nil) ⇒ Array

Returns a JSON representation.

Examples:

Default - full objects for API responses

team.members.as_json
# => [{"objectId"=>"abc", "name"=>"Alice", ...}, ...]

Pointers only for storage

team.members.as_json(pointers_only: true)
# => [{"__type"=>"Pointer", "className"=>"Member", "objectId"=>"abc"}, ...]

Parameters:

  • opts (Hash) (defaults to: nil)

    options for serialization

Options Hash (opts):

  • :pointers_only (Boolean) — default: false

    When true, converts all Parse objects to pointer format. Use this when sending data to Parse Server (saves, webhooks). When false (default), full objects are serialized for API responses.

Returns:

  • (Array)

    a JSON representation



326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
# File 'lib/parse/model/associations/collection_proxy.rb', line 326

def as_json(opts = nil)
  opts ||= {}
  pointers_only = opts.delete(:pointers_only) || opts.delete("pointers_only")

  collection.map do |item|
    if pointers_only && item.respond_to?(:pointer)
      # Convert Parse objects/pointers to pointer format for storage
      ptr = item.pointer
      {
        Parse::Model::TYPE_FIELD => Parse::Model::TYPE_POINTER,
        Parse::Model::KEY_CLASS_NAME => ptr.parse_class,
        Parse::Model::OBJECT_ID => ptr.id,
      }
    elsif item.respond_to?(:as_json)
      item.as_json(opts)
    else
      item
    end
  end
end

#changes_applied!Object

mark that collection changes where applied, which clears dirty tracking.



289
290
291
# File 'lib/parse/model/associations/collection_proxy.rb', line 289

def changes_applied!
  changes_applied
end

#clearObject

clear all items in the collection



106
107
108
# File 'lib/parse/model/associations/collection_proxy.rb', line 106

def clear
  @collection.clear
end

#clear_changes!Object

clears all dirty tracked information.



284
285
286
# File 'lib/parse/model/associations/collection_proxy.rb', line 284

def clear_changes!
  clear_changes_information
end

#countInteger

Returns number of items in the collection.

Returns:

  • (Integer)

    number of items in the collection.



311
312
313
# File 'lib/parse/model/associations/collection_proxy.rb', line 311

def count
  collection.count
end

#destroy!Object

Atomically deletes all items in the array, and marks the field as ‘undefined` directly with the Parse server. This request is sent directly to the Parse backend.



270
271
272
273
274
275
276
# File 'lib/parse/model/associations/collection_proxy.rb', line 270

def destroy!
  return false unless @delegate.respond_to?(:op_destroy!)
  @delegate.send :op_destroy!, @key
  collection_will_change!
  @collection.clear
  reset!
end

#each(&block) ⇒ Object

Alias for Array#each



367
368
369
370
# File 'lib/parse/model/associations/collection_proxy.rb', line 367

def each(&block)
  return collection.enum_for(:each) unless block_given?
  collection.each(&block)
end

#empty?Boolean

true if the collection is empty.

Returns:

  • (Boolean)


348
349
350
# File 'lib/parse/model/associations/collection_proxy.rb', line 348

def empty?
  collection.empty?
end

#first(*args) ⇒ Object

Returns the first item in the collection.

Parameters:

  • args (Hash)

    arguments to pass to Array#first.

Returns:

  • (Object)

    the first item in the collection



295
296
297
# File 'lib/parse/model/associations/collection_proxy.rb', line 295

def first(*args)
  collection.first(*args)
end

#flattenArray

Returns:

  • (Array)

    a flattened one-dimensional array



220
221
222
# File 'lib/parse/model/associations/collection_proxy.rb', line 220

def flatten
  collection.flatten
end

#forward(method, params = nil) ⇒ Object

Forward a method call to the delegate.

Parameters:

  • method (Symbol)

    the name of the method to forward

  • params (Object) (defaults to: nil)

    method parameters

Returns:

  • (Object)

    the return value from the forwarded method.



79
80
81
82
# File 'lib/parse/model/associations/collection_proxy.rb', line 79

def forward(method, params = nil)
  return unless @delegate && @delegate.respond_to?(method)
  params.nil? ? @delegate.send(method) : @delegate.send(method, params)
end

#last(*args) ⇒ Object

Returns the last item in the collection.

Parameters:

  • args (Hash)

    arguments to pass to Array#last.

Returns:

  • (Object)

    the last item in the collection



306
307
308
# File 'lib/parse/model/associations/collection_proxy.rb', line 306

def last(*args)
  collection.last(*args)
end

#loaded?Boolean

true if the collection has been loaded

Returns:

  • (Boolean)


71
72
73
# File 'lib/parse/model/associations/collection_proxy.rb', line 71

def loaded?
  @loaded
end

#map(&block) ⇒ Object

Alias for Array#map



373
374
375
376
# File 'lib/parse/model/associations/collection_proxy.rb', line 373

def map(&block)
  return collection.enum_for(:map) unless block_given?
  collection.map(&block)
end

#notify_will_change!Object

Notifies the delegate that the collection changed.



361
362
363
364
# File 'lib/parse/model/associations/collection_proxy.rb', line 361

def notify_will_change!
  collection_will_change!
  forward "#{@key}_will_change!"
end

#parse_objectsArray<Parse::Object>

Alias to ‘to_a.parse_objects` from Array#parse_objects

Returns:

  • (Array<Parse::Object>)

    an array of Parse Object subclasses representing this collection.



404
405
406
# File 'lib/parse/model/associations/collection_proxy.rb', line 404

def parse_objects
  collection.to_a.parse_objects
end

#parse_pointersArray<Parse::Pointer>

Alias to ‘to_a.parse_pointers` from Array#parse_pointers

Returns:



410
411
412
# File 'lib/parse/model/associations/collection_proxy.rb', line 410

def parse_pointers
  collection.to_a.parse_pointers
end

#reload!Object

Reload and restore the collection to its original set of items.



100
101
102
103
# File 'lib/parse/model/associations/collection_proxy.rb', line 100

def reload!
  reset!
  collection #force reload
end

#remove(*items) ⇒ Object Also known as: delete

Remove items from the collection

Parameters:

  • items (Array)

    items to remove



226
227
228
229
230
231
232
# File 'lib/parse/model/associations/collection_proxy.rb', line 226

def remove(*items)
  notify_will_change! if items.count > 0
  items.each do |item|
    collection.delete item
  end
  @collection
end

#remove!(*items) ⇒ Object

Note:

Parse objects are automatically converted to pointer format

Atomically deletes all items from the array. This request is sent directly to the Parse backend.

Parameters:

  • items (Array)

    items to remove



262
263
264
265
266
# File 'lib/parse/model/associations/collection_proxy.rb', line 262

def remove!(*items)
  return false unless @delegate.respond_to?(:op_remove!)
  @delegate.send :op_remove!, @key, items_to_pointers(items.flatten)
  reset!
end

#reset!Object

Reset the state of the collection.



85
86
87
88
# File 'lib/parse/model/associations/collection_proxy.rb', line 85

def reset!
  @loaded = false
  clear
end

#rollback!Object

Locally restores previous attributes (not from the persistent store)



279
280
281
# File 'lib/parse/model/associations/collection_proxy.rb', line 279

def rollback!
  restore_attributes
end

#secondObject

Returns the second item in the collection.

Returns:

  • (Object)

    the second item in the collection



300
301
302
# File 'lib/parse/model/associations/collection_proxy.rb', line 300

def second
  collection.second
end

#select(&block) ⇒ Object

Alias for Array#select



379
380
381
382
# File 'lib/parse/model/associations/collection_proxy.rb', line 379

def select(&block)
  return collection.enum_for(:select) unless block_given?
  collection.select(&block)
end

#set_collection!(list) ⇒ Array

Set the internal collection of items without dirty tracking or change notifications.

Returns:

  • (Array)

    the collection



120
121
122
# File 'lib/parse/model/associations/collection_proxy.rb', line 120

def set_collection!(list)
  @collection = list
end

#to_aArray Also known as: to_ary

Returns:



111
112
113
# File 'lib/parse/model/associations/collection_proxy.rb', line 111

def to_a
  collection.to_a
end

#uniq(&block) ⇒ Object

Alias for Array#uniq



385
386
387
388
# File 'lib/parse/model/associations/collection_proxy.rb', line 385

def uniq(&block)
  return collection.uniq(&block) if block_given?
  return collection.uniq
end

#uniq!(&block) ⇒ Object

Alias for Array#uniq!



391
392
393
394
395
# File 'lib/parse/model/associations/collection_proxy.rb', line 391

def uniq!(&block)
  notify_will_change!
  return collection.uniq!(&block) if block_given?
  return collection.uniq!
end

#|(items) ⇒ Array

Set Union - Returns a new array by joining two arrays, excluding any duplicates and preserving the order from the original array. It compares elements using their hash and eql? methods for efficiency. See Array#|

Examples:

[ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]

Parameters:

  • items (Array)

    items to uniquely add

Returns:

  • (Array)

    array with unique items

See Also:



177
178
179
# File 'lib/parse/model/associations/collection_proxy.rb', line 177

def |(items)
  collection | [items].flatten
end