parse-stack-next 4.5.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/.bundle/config +2 -0
- data/.env.sample +112 -0
- data/.env.test +10 -0
- data/.github/workflows/ruby.yml +36 -0
- data/.gitignore +49 -0
- data/.ruby-version +1 -0
- data/.solargraph.yml +22 -0
- data/CHANGELOG.md +5816 -0
- data/Gemfile +30 -0
- data/Gemfile.lock +175 -0
- data/LICENSE.txt +23 -0
- data/Makefile +63 -0
- data/README.md +5655 -0
- data/Rakefile +573 -0
- data/bin/console +38 -0
- data/bin/parse-console +136 -0
- data/bin/server +17 -0
- data/bin/setup +7 -0
- data/config/parse-config.json +12 -0
- data/docs/TEST_SERVER.md +271 -0
- data/docs/_config.yml +1 -0
- data/docs/mcp_guide.md +3484 -0
- data/docs/mongodb_direct_guide.md +1348 -0
- data/docs/mongodb_index_optimization_guide.md +631 -0
- data/examples/transaction_example.rb +219 -0
- data/lib/parse/acl_scope.rb +728 -0
- data/lib/parse/agent/cancellation_token.rb +80 -0
- data/lib/parse/agent/constraint_translator.rb +480 -0
- data/lib/parse/agent/describe.rb +420 -0
- data/lib/parse/agent/errors.rb +133 -0
- data/lib/parse/agent/mcp_client.rb +557 -0
- data/lib/parse/agent/mcp_dispatcher.rb +1023 -0
- data/lib/parse/agent/mcp_rack_app.rb +1143 -0
- data/lib/parse/agent/mcp_server.rb +376 -0
- data/lib/parse/agent/metadata_audit.rb +259 -0
- data/lib/parse/agent/metadata_dsl.rb +733 -0
- data/lib/parse/agent/metadata_registry.rb +794 -0
- data/lib/parse/agent/pipeline_validator.rb +82 -0
- data/lib/parse/agent/prompts.rb +351 -0
- data/lib/parse/agent/rate_limiter.rb +158 -0
- data/lib/parse/agent/relation_graph.rb +162 -0
- data/lib/parse/agent/result_formatter.rb +453 -0
- data/lib/parse/agent/tools.rb +5489 -0
- data/lib/parse/agent.rb +3249 -0
- data/lib/parse/api/aggregate.rb +79 -0
- data/lib/parse/api/all.rb +26 -0
- data/lib/parse/api/analytics.rb +18 -0
- data/lib/parse/api/batch.rb +33 -0
- data/lib/parse/api/cloud_functions.rb +58 -0
- data/lib/parse/api/config.rb +125 -0
- data/lib/parse/api/files.rb +29 -0
- data/lib/parse/api/hooks.rb +117 -0
- data/lib/parse/api/objects.rb +146 -0
- data/lib/parse/api/path_segment.rb +75 -0
- data/lib/parse/api/push.rb +20 -0
- data/lib/parse/api/schema.rb +49 -0
- data/lib/parse/api/server.rb +50 -0
- data/lib/parse/api/sessions.rb +24 -0
- data/lib/parse/api/users.rb +250 -0
- data/lib/parse/atlas_search/index_manager.rb +353 -0
- data/lib/parse/atlas_search/result.rb +204 -0
- data/lib/parse/atlas_search/search_builder.rb +604 -0
- data/lib/parse/atlas_search/session.rb +253 -0
- data/lib/parse/atlas_search.rb +995 -0
- data/lib/parse/client/authentication.rb +97 -0
- data/lib/parse/client/batch.rb +234 -0
- data/lib/parse/client/body_builder.rb +240 -0
- data/lib/parse/client/caching.rb +203 -0
- data/lib/parse/client/logging.rb +293 -0
- data/lib/parse/client/profiling.rb +181 -0
- data/lib/parse/client/protocol.rb +91 -0
- data/lib/parse/client/request.rb +233 -0
- data/lib/parse/client/response.rb +208 -0
- data/lib/parse/client.rb +1104 -0
- data/lib/parse/clp_scope.rb +361 -0
- data/lib/parse/live_query/circuit_breaker.rb +256 -0
- data/lib/parse/live_query/client.rb +1001 -0
- data/lib/parse/live_query/configuration.rb +224 -0
- data/lib/parse/live_query/event.rb +115 -0
- data/lib/parse/live_query/event_queue.rb +272 -0
- data/lib/parse/live_query/health_monitor.rb +214 -0
- data/lib/parse/live_query/logging.rb +149 -0
- data/lib/parse/live_query/subscription.rb +294 -0
- data/lib/parse/live_query.rb +163 -0
- data/lib/parse/lookup_rewriter.rb +445 -0
- data/lib/parse/model/acl.rb +968 -0
- data/lib/parse/model/associations/belongs_to.rb +275 -0
- data/lib/parse/model/associations/collection_proxy.rb +435 -0
- data/lib/parse/model/associations/has_many.rb +597 -0
- data/lib/parse/model/associations/has_one.rb +158 -0
- data/lib/parse/model/associations/pointer_collection_proxy.rb +134 -0
- data/lib/parse/model/associations/relation_collection_proxy.rb +177 -0
- data/lib/parse/model/bytes.rb +62 -0
- data/lib/parse/model/classes/audience.rb +262 -0
- data/lib/parse/model/classes/installation.rb +363 -0
- data/lib/parse/model/classes/job_schedule.rb +153 -0
- data/lib/parse/model/classes/job_status.rb +264 -0
- data/lib/parse/model/classes/product.rb +75 -0
- data/lib/parse/model/classes/push_status.rb +263 -0
- data/lib/parse/model/classes/role.rb +751 -0
- data/lib/parse/model/classes/session.rb +201 -0
- data/lib/parse/model/classes/user.rb +943 -0
- data/lib/parse/model/clp.rb +544 -0
- data/lib/parse/model/core/actions.rb +1268 -0
- data/lib/parse/model/core/builder.rb +139 -0
- data/lib/parse/model/core/create_lock.rb +386 -0
- data/lib/parse/model/core/describe.rb +382 -0
- data/lib/parse/model/core/enhanced_change_tracking.rb +159 -0
- data/lib/parse/model/core/errors.rb +38 -0
- data/lib/parse/model/core/fetching.rb +566 -0
- data/lib/parse/model/core/field_guards.rb +220 -0
- data/lib/parse/model/core/indexing.rb +382 -0
- data/lib/parse/model/core/parse_reference.rb +407 -0
- data/lib/parse/model/core/properties.rb +809 -0
- data/lib/parse/model/core/querying.rb +491 -0
- data/lib/parse/model/core/schema.rb +202 -0
- data/lib/parse/model/core/search_indexing.rb +174 -0
- data/lib/parse/model/date.rb +88 -0
- data/lib/parse/model/email.rb +213 -0
- data/lib/parse/model/file.rb +527 -0
- data/lib/parse/model/geojson.rb +271 -0
- data/lib/parse/model/geopoint.rb +261 -0
- data/lib/parse/model/model.rb +260 -0
- data/lib/parse/model/object.rb +2068 -0
- data/lib/parse/model/phone.rb +520 -0
- data/lib/parse/model/pointer.rb +443 -0
- data/lib/parse/model/polygon.rb +406 -0
- data/lib/parse/model/push.rb +975 -0
- data/lib/parse/model/shortnames.rb +8 -0
- data/lib/parse/model/time_zone.rb +141 -0
- data/lib/parse/model/validations/uniqueness_validator.rb +97 -0
- data/lib/parse/model/validations.rb +96 -0
- data/lib/parse/mongodb.rb +2300 -0
- data/lib/parse/pipeline_security.rb +554 -0
- data/lib/parse/query/constraint.rb +198 -0
- data/lib/parse/query/constraints.rb +3279 -0
- data/lib/parse/query/cursor.rb +434 -0
- data/lib/parse/query/n_plus_one_detector.rb +445 -0
- data/lib/parse/query/operation.rb +104 -0
- data/lib/parse/query/ordering.rb +66 -0
- data/lib/parse/query.rb +7028 -0
- data/lib/parse/schema/index_migrator.rb +291 -0
- data/lib/parse/schema/search_index_migrator.rb +289 -0
- data/lib/parse/schema.rb +494 -0
- data/lib/parse/stack/generators/rails.rb +40 -0
- data/lib/parse/stack/generators/templates/model.erb +51 -0
- data/lib/parse/stack/generators/templates/model_installation.rb +4 -0
- data/lib/parse/stack/generators/templates/model_role.rb +4 -0
- data/lib/parse/stack/generators/templates/model_session.rb +4 -0
- data/lib/parse/stack/generators/templates/model_user.rb +11 -0
- data/lib/parse/stack/generators/templates/parse.rb +12 -0
- data/lib/parse/stack/generators/templates/webhooks.rb +10 -0
- data/lib/parse/stack/railtie.rb +18 -0
- data/lib/parse/stack/tasks.rb +563 -0
- data/lib/parse/stack/version.rb +11 -0
- data/lib/parse/stack.rb +455 -0
- data/lib/parse/two_factor_auth/user_extension.rb +449 -0
- data/lib/parse/two_factor_auth.rb +310 -0
- data/lib/parse/webhooks/payload.rb +360 -0
- data/lib/parse/webhooks/registration.rb +199 -0
- data/lib/parse/webhooks/replay_protection.rb +189 -0
- data/lib/parse/webhooks.rb +510 -0
- data/lib/parse-stack-next.rb +5 -0
- data/lib/parse-stack.rb +5 -0
- data/parse-stack-next.gemspec +82 -0
- data/parse-stack.png +0 -0
- data/scripts/debug-ips.js +35 -0
- data/scripts/docker/Dockerfile.parse +13 -0
- data/scripts/docker/atlas-init.js +284 -0
- data/scripts/docker/docker-compose.atlas.yml +76 -0
- data/scripts/docker/docker-compose.test.yml +106 -0
- data/scripts/docker/mongo-init.js +21 -0
- data/scripts/eval_mcp_with_lm_studio.rb +274 -0
- data/scripts/start-parse.sh +90 -0
- data/scripts/start_mcp_server.rb +78 -0
- data/scripts/test_server_connection.rb +82 -0
- metadata +377 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "active_model"
|
|
5
|
+
require "active_support"
|
|
6
|
+
require "active_support/inflector"
|
|
7
|
+
require "active_support/core_ext/object"
|
|
8
|
+
require_relative "../pointer"
|
|
9
|
+
|
|
10
|
+
module Parse
|
|
11
|
+
# We use a delegate pattern to send notifications to the parent whenever the content of the internal array changes.
|
|
12
|
+
# The main requirement to using the proxy is to provide the list of initial items if any,
|
|
13
|
+
# the owner to be notified and the name of the attribute 'key'. With that, anytime the array
|
|
14
|
+
# will change, we will notify the delegate by sending :'key'_will_change! . The proxy can also
|
|
15
|
+
# be lazy when fetching the contents of the collection. Whenever the collection is accessed and
|
|
16
|
+
# the list is in a "not loaded" state (empty and loaded == false), we will send :'key_fetch!' to the delegate in order to
|
|
17
|
+
# populate the collection.
|
|
18
|
+
|
|
19
|
+
# A CollectionProxy is a special type of array wrapper that notifies a delegate
|
|
20
|
+
# object about changes to the array in order to perform dirty tracking. This is
|
|
21
|
+
# used for all Array properties in Parse::Objects. Subclasses of {CollectionProxy} are
|
|
22
|
+
# also available for supporting different association types such as an array of Parse pointers
|
|
23
|
+
# and Parse relations.
|
|
24
|
+
# @see PointerCollectionProxy
|
|
25
|
+
# @see RelationCollectionProxy
|
|
26
|
+
class CollectionProxy
|
|
27
|
+
include ::ActiveModel::Model
|
|
28
|
+
include ::ActiveModel::Dirty
|
|
29
|
+
include ::Enumerable
|
|
30
|
+
|
|
31
|
+
# @!attribute [r] delegate
|
|
32
|
+
# The object to be notified of changes to the collection.
|
|
33
|
+
# @return [Object]
|
|
34
|
+
|
|
35
|
+
# @!attribute [rw] loaded
|
|
36
|
+
# @return [Boolean] true/false whether the collection has been loaded.
|
|
37
|
+
|
|
38
|
+
# @!attribute [r] parse_class
|
|
39
|
+
# For some subclasses, this helps typecast the items in the collection.
|
|
40
|
+
# @return [String]
|
|
41
|
+
|
|
42
|
+
# @!attribute [r] key
|
|
43
|
+
# the name of the property key to use when sending notifications for _will_change! and _fetch!
|
|
44
|
+
# @return [String]
|
|
45
|
+
|
|
46
|
+
# The writer for :collection is defined explicitly below with dirty-tracking
|
|
47
|
+
# notification; do not declare attr_writer :collection here.
|
|
48
|
+
attr_accessor :loaded, :parse_class
|
|
49
|
+
attr_reader :delegate, :key
|
|
50
|
+
|
|
51
|
+
# This is to use dirty tracking within the proxy
|
|
52
|
+
define_attribute_methods :collection
|
|
53
|
+
|
|
54
|
+
# Create a new CollectionProxy instance.
|
|
55
|
+
# @param collection [Array] the initial items to add to the collection.
|
|
56
|
+
# @param delegate [Object] the owner of the object that will receive the notifications.
|
|
57
|
+
# @param key [Symbol] the name of the key to use when sending notifications for _will_change! and _fetch!
|
|
58
|
+
# @param parse_class [String] (Optional) the Parse class type are the items of the collection.
|
|
59
|
+
# This is used to typecast the objects in the array to a particular Parse Object type.
|
|
60
|
+
# @see PointerCollectionProxy
|
|
61
|
+
# @see RelationCollectionProxy
|
|
62
|
+
def initialize(collection = nil, delegate: nil, key: nil, parse_class: nil)
|
|
63
|
+
@delegate = delegate
|
|
64
|
+
@key = key.to_sym if key.present?
|
|
65
|
+
@collection = collection.is_a?(Array) ? collection : []
|
|
66
|
+
@loaded = @collection.count > 0
|
|
67
|
+
@parse_class = parse_class
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# true if the collection has been loaded
|
|
71
|
+
def loaded?
|
|
72
|
+
@loaded
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Forward a method call to the delegate.
|
|
76
|
+
# @param method [Symbol] the name of the method to forward
|
|
77
|
+
# @param params [Object] method parameters
|
|
78
|
+
# @return [Object] the return value from the forwarded method.
|
|
79
|
+
def forward(method, params = nil)
|
|
80
|
+
return unless @delegate && @delegate.respond_to?(method)
|
|
81
|
+
params.nil? ? @delegate.send(method) : @delegate.send(method, params)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Reset the state of the collection.
|
|
85
|
+
def reset!
|
|
86
|
+
@loaded = false
|
|
87
|
+
clear
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @return [Boolean] true if two collection proxies have similar items.
|
|
91
|
+
def ==(other_list)
|
|
92
|
+
if other_list.is_a?(Array)
|
|
93
|
+
return @collection == other_list
|
|
94
|
+
elsif other_list.is_a?(Parse::CollectionProxy)
|
|
95
|
+
return @collection == other_list.instance_variable_get(:@collection)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Reload and restore the collection to its original set of items.
|
|
100
|
+
def reload!
|
|
101
|
+
reset!
|
|
102
|
+
collection #force reload
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# clear all items in the collection
|
|
106
|
+
def clear
|
|
107
|
+
@collection.clear
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# @return [Array]
|
|
111
|
+
def to_a
|
|
112
|
+
collection.to_a
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
alias_method :to_ary, :to_a
|
|
116
|
+
|
|
117
|
+
# Set the internal collection of items *without* dirty tracking or
|
|
118
|
+
# change notifications.
|
|
119
|
+
# @return [Array] the collection
|
|
120
|
+
def set_collection!(list)
|
|
121
|
+
@collection = list
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @!attribute [rw] collection
|
|
125
|
+
# The internal backing store of the collection containing the content. This value is lazily
|
|
126
|
+
# loaded for some subclasses.
|
|
127
|
+
# @note If you modify this directly, it is highly recommended that you
|
|
128
|
+
# call {CollectionProxy#notify_will_change!} to notify the dirty tracking system.
|
|
129
|
+
# @return [Array] contents of the collection.
|
|
130
|
+
def collection
|
|
131
|
+
if @collection.empty? && @loaded == false
|
|
132
|
+
@collection = forward(:"#{@key}_fetch!") || @collection || []
|
|
133
|
+
@loaded = true
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
@collection
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def collection=(c)
|
|
140
|
+
notify_will_change!
|
|
141
|
+
@collection = c
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Add items to the collection
|
|
145
|
+
# @param items [Array] items to add
|
|
146
|
+
def add(*items)
|
|
147
|
+
notify_will_change! if items.count > 0
|
|
148
|
+
items.each do |item|
|
|
149
|
+
collection.push item
|
|
150
|
+
end
|
|
151
|
+
@collection
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
alias_method :push, :add
|
|
155
|
+
|
|
156
|
+
# Add items to the collection if they don't already exist
|
|
157
|
+
# @param items [Array] items to uniquely add
|
|
158
|
+
# @return [Array] the collection.
|
|
159
|
+
def add_unique(*items)
|
|
160
|
+
return unless items.count > 0
|
|
161
|
+
notify_will_change!
|
|
162
|
+
@collection = collection | items.flatten
|
|
163
|
+
@collection
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
alias_method :push_unique, :add_unique
|
|
167
|
+
|
|
168
|
+
# Set Union - Returns a new array by joining two arrays, excluding
|
|
169
|
+
# any duplicates and preserving the order from the original array.
|
|
170
|
+
# It compares elements using their hash and eql? methods for efficiency.
|
|
171
|
+
# See {https://docs.ruby-lang.org/en/2.0.0/Array.html#method-i-hash Array#|}
|
|
172
|
+
# @example
|
|
173
|
+
# [ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]
|
|
174
|
+
# @param items [Array] items to uniquely add
|
|
175
|
+
# @see #add_unique
|
|
176
|
+
# @return [Array] array with unique items
|
|
177
|
+
def |(items)
|
|
178
|
+
collection | [items].flatten
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Set Intersection - Returns a new array containing unique elements common
|
|
182
|
+
# to the two arrays. The order is preserved from the original array.
|
|
183
|
+
#
|
|
184
|
+
# It compares elements using their hash and eql? methods for efficiency.
|
|
185
|
+
# See {https://ruby-doc.org/core-2.4.1/Array.html#method-i-26 Array#&}
|
|
186
|
+
# @example
|
|
187
|
+
# [ 1, 1, 3, 5 ] & [ 3, 2, 1 ] #=> [ 1, 3 ]
|
|
188
|
+
# [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ]
|
|
189
|
+
# @param other_ary [Array]
|
|
190
|
+
# @return [Array] intersection array
|
|
191
|
+
def &(other_ary)
|
|
192
|
+
collection & [other_ary].flatten
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
# Alias {https://ruby-doc.org/core-2.4.1/Array.html#method-i-2D Array Difference}.
|
|
196
|
+
# Returns a new array that is a copy of the original array, removing any
|
|
197
|
+
# items that also appear in other_ary. The order is preserved from the
|
|
198
|
+
# original array.
|
|
199
|
+
# @example
|
|
200
|
+
# [ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]
|
|
201
|
+
# @param other_ary [Array]
|
|
202
|
+
# @return [Array] delta array
|
|
203
|
+
def -(other_ary)
|
|
204
|
+
collection - [other_ary].flatten
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Alias {https://ruby-doc.org/core-2.4.1/Array.html#method-i-2B Array Concatenation}.
|
|
208
|
+
# Returns a new array built by concatenating the two arrays together to
|
|
209
|
+
# produce a third array.
|
|
210
|
+
# @example
|
|
211
|
+
# [ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ]
|
|
212
|
+
# @param other_ary [Array]
|
|
213
|
+
# @return [Array] concatenated array
|
|
214
|
+
def +(other_ary)
|
|
215
|
+
collection + [other_ary].flatten.to_a
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# Alias {https://ruby-doc.org/core-2.4.1/Array.html#method-i-flatten Array flattening}.
|
|
219
|
+
# @return [Array] a flattened one-dimensional array
|
|
220
|
+
def flatten
|
|
221
|
+
collection.flatten
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Remove items from the collection
|
|
225
|
+
# @param items [Array] items to remove
|
|
226
|
+
def remove(*items)
|
|
227
|
+
notify_will_change! if items.count > 0
|
|
228
|
+
items.each do |item|
|
|
229
|
+
collection.delete item
|
|
230
|
+
end
|
|
231
|
+
@collection
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
alias_method :delete, :remove
|
|
235
|
+
|
|
236
|
+
# Atomically adds all items from the array.
|
|
237
|
+
# This request is sent directly to the Parse backend.
|
|
238
|
+
# @param items [Array] items to uniquely add
|
|
239
|
+
# @note Parse objects are automatically converted to pointer format
|
|
240
|
+
# @see #add_unique!
|
|
241
|
+
def add!(*items)
|
|
242
|
+
return false unless @delegate.respond_to?(:op_add!)
|
|
243
|
+
@delegate.send :op_add!, @key, items_to_pointers(items.flatten)
|
|
244
|
+
reset!
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
# Atomically adds all items from the array that are not already part of the collection.
|
|
248
|
+
# This request is sent directly to the Parse backend.
|
|
249
|
+
# @param items [Array] items to uniquely add
|
|
250
|
+
# @note Parse objects are automatically converted to pointer format
|
|
251
|
+
# @see #add!
|
|
252
|
+
def add_unique!(*items)
|
|
253
|
+
return false unless @delegate.respond_to?(:op_add_unique!)
|
|
254
|
+
@delegate.send :op_add_unique!, @key, items_to_pointers(items.flatten)
|
|
255
|
+
reset!
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
# Atomically deletes all items from the array. This request is sent
|
|
259
|
+
# directly to the Parse backend.
|
|
260
|
+
# @param items [Array] items to remove
|
|
261
|
+
# @note Parse objects are automatically converted to pointer format
|
|
262
|
+
def remove!(*items)
|
|
263
|
+
return false unless @delegate.respond_to?(:op_remove!)
|
|
264
|
+
@delegate.send :op_remove!, @key, items_to_pointers(items.flatten)
|
|
265
|
+
reset!
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
# Atomically deletes all items in the array, and marks the field as `undefined` directly
|
|
269
|
+
# with the Parse server. This request is sent directly to the Parse backend.
|
|
270
|
+
def destroy!
|
|
271
|
+
return false unless @delegate.respond_to?(:op_destroy!)
|
|
272
|
+
@delegate.send :op_destroy!, @key
|
|
273
|
+
collection_will_change!
|
|
274
|
+
@collection.clear
|
|
275
|
+
reset!
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# Locally restores previous attributes (not from the persistent store)
|
|
279
|
+
def rollback!
|
|
280
|
+
restore_attributes
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# clears all dirty tracked information.
|
|
284
|
+
def clear_changes!
|
|
285
|
+
clear_changes_information
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
# mark that collection changes where applied, which clears dirty tracking.
|
|
289
|
+
def changes_applied!
|
|
290
|
+
changes_applied
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
# @param args [Hash] arguments to pass to Array#first.
|
|
294
|
+
# @return [Object] the first item in the collection
|
|
295
|
+
def first(*args)
|
|
296
|
+
collection.first(*args)
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# @return [Object] the second item in the collection
|
|
300
|
+
def second
|
|
301
|
+
collection.second
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# @param args [Hash] arguments to pass to Array#last.
|
|
305
|
+
# @return [Object] the last item in the collection
|
|
306
|
+
def last(*args)
|
|
307
|
+
collection.last(*args)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# @return [Integer] number of items in the collection.
|
|
311
|
+
def count
|
|
312
|
+
collection.count
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# @return [Array] a JSON representation
|
|
316
|
+
# @param opts [Hash] options for serialization
|
|
317
|
+
# @option opts [Boolean] :pointers_only (false) When true, converts all Parse objects
|
|
318
|
+
# to pointer format. Use this when sending data to Parse Server (saves, webhooks).
|
|
319
|
+
# When false (default), full objects are serialized for API responses.
|
|
320
|
+
# @example Default - full objects for API responses
|
|
321
|
+
# team.members.as_json
|
|
322
|
+
# # => [{"objectId"=>"abc", "name"=>"Alice", ...}, ...]
|
|
323
|
+
# @example Pointers only for storage
|
|
324
|
+
# team.members.as_json(pointers_only: true)
|
|
325
|
+
# # => [{"__type"=>"Pointer", "className"=>"Member", "objectId"=>"abc"}, ...]
|
|
326
|
+
def as_json(opts = nil)
|
|
327
|
+
opts ||= {}
|
|
328
|
+
pointers_only = opts.delete(:pointers_only) || opts.delete("pointers_only")
|
|
329
|
+
|
|
330
|
+
collection.map do |item|
|
|
331
|
+
if pointers_only && item.respond_to?(:pointer)
|
|
332
|
+
# Convert Parse objects/pointers to pointer format for storage
|
|
333
|
+
ptr = item.pointer
|
|
334
|
+
{
|
|
335
|
+
Parse::Model::TYPE_FIELD => Parse::Model::TYPE_POINTER,
|
|
336
|
+
Parse::Model::KEY_CLASS_NAME => ptr.parse_class,
|
|
337
|
+
Parse::Model::OBJECT_ID => ptr.id,
|
|
338
|
+
}
|
|
339
|
+
elsif item.respond_to?(:as_json)
|
|
340
|
+
item.as_json(opts)
|
|
341
|
+
else
|
|
342
|
+
item
|
|
343
|
+
end
|
|
344
|
+
end
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# true if the collection is empty.
|
|
348
|
+
def empty?
|
|
349
|
+
collection.empty?
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Append items to the collection
|
|
353
|
+
def <<(*list)
|
|
354
|
+
if list.count > 0
|
|
355
|
+
notify_will_change!
|
|
356
|
+
list.flatten.each { |e| collection.push(e) }
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# Notifies the delegate that the collection changed.
|
|
361
|
+
def notify_will_change!
|
|
362
|
+
collection_will_change!
|
|
363
|
+
forward "#{@key}_will_change!"
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# Alias for Array#each
|
|
367
|
+
def each(&block)
|
|
368
|
+
return collection.enum_for(:each) unless block_given?
|
|
369
|
+
collection.each(&block)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
# Alias for Array#map
|
|
373
|
+
def map(&block)
|
|
374
|
+
return collection.enum_for(:map) unless block_given?
|
|
375
|
+
collection.map(&block)
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# Alias for Array#select
|
|
379
|
+
def select(&block)
|
|
380
|
+
return collection.enum_for(:select) unless block_given?
|
|
381
|
+
collection.select(&block)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Alias for Array#uniq
|
|
385
|
+
def uniq(&block)
|
|
386
|
+
return collection.uniq(&block) if block_given?
|
|
387
|
+
return collection.uniq
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
# Alias for Array#uniq!
|
|
391
|
+
def uniq!(&block)
|
|
392
|
+
notify_will_change!
|
|
393
|
+
return collection.uniq!(&block) if block_given?
|
|
394
|
+
return collection.uniq!
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
# @!visibility private
|
|
398
|
+
def inspect
|
|
399
|
+
"#<#{self.class} changed?=#{changed?} @collection=#{@collection.inspect} >"
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
# Alias to `to_a.parse_objects` from Array#parse_objects
|
|
403
|
+
# @return [Array<Parse::Object>] an array of Parse Object subclasses representing this collection.
|
|
404
|
+
def parse_objects
|
|
405
|
+
collection.to_a.parse_objects
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
# Alias to `to_a.parse_pointers` from Array#parse_pointers
|
|
409
|
+
# @return [Array<Parse::Pointer>] an array of pointers representing this collection.
|
|
410
|
+
def parse_pointers
|
|
411
|
+
collection.to_a.parse_pointers
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
private
|
|
415
|
+
|
|
416
|
+
# Convert items to pointer format for atomic operations.
|
|
417
|
+
# Parse objects/pointers are converted to pointer hashes, other items pass through.
|
|
418
|
+
# @param items [Array] items to convert
|
|
419
|
+
# @return [Array] items with Parse objects converted to pointer format
|
|
420
|
+
def items_to_pointers(items)
|
|
421
|
+
items.map do |item|
|
|
422
|
+
if item.respond_to?(:pointer)
|
|
423
|
+
ptr = item.pointer
|
|
424
|
+
{
|
|
425
|
+
Parse::Model::TYPE_FIELD => Parse::Model::TYPE_POINTER,
|
|
426
|
+
Parse::Model::KEY_CLASS_NAME => ptr.parse_class,
|
|
427
|
+
Parse::Model::OBJECT_ID => ptr.id,
|
|
428
|
+
}
|
|
429
|
+
else
|
|
430
|
+
item
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
end
|
|
435
|
+
end
|