parse-stack 1.7.3 → 1.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ruby.yml +36 -0
  3. data/.solargraph.yml +23 -0
  4. data/.travis.yml +6 -3
  5. data/Changes.md +84 -22
  6. data/Gemfile +14 -12
  7. data/Gemfile.lock +110 -60
  8. data/README.md +67 -24
  9. data/Rakefile +14 -14
  10. data/bin/parse-console +1 -0
  11. data/lib/parse/api/aggregate.rb +59 -0
  12. data/lib/parse/api/all.rb +2 -1
  13. data/lib/parse/api/analytics.rb +0 -3
  14. data/lib/parse/api/batch.rb +3 -5
  15. data/lib/parse/api/cloud_functions.rb +0 -3
  16. data/lib/parse/api/config.rb +0 -4
  17. data/lib/parse/api/files.rb +3 -7
  18. data/lib/parse/api/hooks.rb +4 -8
  19. data/lib/parse/api/objects.rb +9 -14
  20. data/lib/parse/api/push.rb +0 -4
  21. data/lib/parse/api/schema.rb +2 -6
  22. data/lib/parse/api/server.rb +4 -7
  23. data/lib/parse/api/sessions.rb +2 -5
  24. data/lib/parse/api/users.rb +9 -14
  25. data/lib/parse/client.rb +55 -50
  26. data/lib/parse/client/authentication.rb +29 -33
  27. data/lib/parse/client/batch.rb +8 -11
  28. data/lib/parse/client/body_builder.rb +19 -20
  29. data/lib/parse/client/caching.rb +23 -28
  30. data/lib/parse/client/protocol.rb +11 -12
  31. data/lib/parse/client/request.rb +4 -6
  32. data/lib/parse/client/response.rb +5 -7
  33. data/lib/parse/model/acl.rb +14 -12
  34. data/lib/parse/model/associations/belongs_to.rb +19 -24
  35. data/lib/parse/model/associations/collection_proxy.rb +328 -317
  36. data/lib/parse/model/associations/has_many.rb +22 -27
  37. data/lib/parse/model/associations/has_one.rb +7 -12
  38. data/lib/parse/model/associations/pointer_collection_proxy.rb +5 -13
  39. data/lib/parse/model/associations/relation_collection_proxy.rb +5 -9
  40. data/lib/parse/model/bytes.rb +8 -10
  41. data/lib/parse/model/classes/installation.rb +2 -4
  42. data/lib/parse/model/classes/product.rb +2 -5
  43. data/lib/parse/model/classes/role.rb +3 -5
  44. data/lib/parse/model/classes/session.rb +2 -5
  45. data/lib/parse/model/classes/user.rb +21 -17
  46. data/lib/parse/model/core/actions.rb +31 -46
  47. data/lib/parse/model/core/builder.rb +6 -6
  48. data/lib/parse/model/core/errors.rb +0 -1
  49. data/lib/parse/model/core/fetching.rb +45 -50
  50. data/lib/parse/model/core/properties.rb +53 -68
  51. data/lib/parse/model/core/querying.rb +292 -282
  52. data/lib/parse/model/core/schema.rb +89 -92
  53. data/lib/parse/model/date.rb +16 -23
  54. data/lib/parse/model/file.rb +171 -174
  55. data/lib/parse/model/geopoint.rb +12 -16
  56. data/lib/parse/model/model.rb +31 -37
  57. data/lib/parse/model/object.rb +58 -70
  58. data/lib/parse/model/pointer.rb +177 -176
  59. data/lib/parse/model/push.rb +8 -10
  60. data/lib/parse/model/shortnames.rb +1 -2
  61. data/lib/parse/model/time_zone.rb +3 -5
  62. data/lib/parse/query.rb +70 -37
  63. data/lib/parse/query/constraint.rb +4 -6
  64. data/lib/parse/query/constraints.rb +62 -20
  65. data/lib/parse/query/operation.rb +8 -11
  66. data/lib/parse/query/ordering.rb +45 -49
  67. data/lib/parse/stack.rb +15 -11
  68. data/lib/parse/stack/generators/rails.rb +28 -30
  69. data/lib/parse/stack/generators/templates/model.erb +5 -6
  70. data/lib/parse/stack/generators/templates/model_installation.rb +0 -1
  71. data/lib/parse/stack/generators/templates/model_role.rb +0 -1
  72. data/lib/parse/stack/generators/templates/model_session.rb +0 -1
  73. data/lib/parse/stack/generators/templates/model_user.rb +0 -1
  74. data/lib/parse/stack/generators/templates/parse.rb +9 -9
  75. data/lib/parse/stack/generators/templates/webhooks.rb +1 -2
  76. data/lib/parse/stack/railtie.rb +2 -4
  77. data/lib/parse/stack/tasks.rb +70 -86
  78. data/lib/parse/stack/version.rb +1 -1
  79. data/lib/parse/webhooks.rb +19 -26
  80. data/lib/parse/webhooks/payload.rb +26 -28
  81. data/lib/parse/webhooks/registration.rb +23 -31
  82. data/parse-stack.gemspec +28 -28
  83. data/parse-stack.png +0 -0
  84. metadata +27 -25
  85. data/.github/parse-ruby-sdk.png +0 -0
@@ -1,199 +1,200 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'active_model'
5
- require 'active_support'
6
- require 'active_support/inflector'
7
- require 'active_support/core_ext'
8
- require 'active_model_serializers'
9
- require_relative 'model'
4
+ require "active_model"
5
+ require "active_support"
6
+ require "active_support/inflector"
7
+ require "active_support/core_ext"
8
+ require "active_model_serializers"
9
+ require_relative "model"
10
+
10
11
  module Parse
11
12
 
12
- # The Pointer class represents the pointer type in Parse and is the superclass
13
- # of Parse::Object types. A pointer can be considered a type of Parse::Object
14
- # in which only the class name and id is known. In most cases, you may not
15
- # deal with Parse::Pointer objects directly if you have defined all your
16
- # Parse::Object subclasses.
17
- #
18
- # A `Parse::Pointer` only contains data about the specific Parse class and
19
- # the `id` for the object. Therefore, creating an instance of any
20
- # Parse::Object subclass with only the `:id` field set will be
21
- # considered in "pointer" state even though its specific class is not
22
- # `Parse::Pointer` type. The only case that you may have a Parse::Pointer
23
- # is in the case where an object was received for one of your classes and
24
- # the framework has no registered class handler for it.
25
- # Assume you have the tables `Post`, `Comment` and `Author` defined in your
26
- # remote Parse database, but have only defined `Post` and `Commentary`
27
- # locally.
28
- # @example
29
- # class Post < Parse::Object
30
- # end
31
- #
32
- # class Commentary < Parse::Object
33
- # belongs_to :post
34
- # belongs_to :author
35
- # end
36
- #
37
- # comment = Commentary.first
38
- # comment.post? # true because it is non-nil
39
- # comment.artist? # true because it is non-nil
40
- #
41
- # # both are true because they are in a Pointer state
42
- # comment.post.pointer? # true
43
- # comment.author.pointer? # true
44
- #
45
- # # we have defined a Post class handler
46
- # comment.post # <Post @parse_class="Post", @id="xdqcCqfngz">
47
- #
48
- # # we have not defined an Author class handler
49
- # comment.author # <Parse::Pointer @parse_class="Author", @id="hZLbW6ofKC">
50
- #
51
- #
52
- # comment.post.fetch # fetch the relation
53
- # comment.post.pointer? # false, it is now a full object.
54
- #
55
- # The effect is that for any unknown classes that the framework encounters,
56
- # it will generate Parse::Pointer instances until you define those classes
57
- # with valid properties and associations. While this might be ok for some
58
- # classes you do not use, we still recommend defining all your Parse classes
59
- # locally in the framework.
60
- #
61
- # Once you have a subclass, you may also create a Parse::Pointer object using
62
- # the _pointer_ method.
63
- # @example
64
- # Parse::User.pointer("123456") # => Parse::Pointer for "_User" class
65
- #
66
- # @see Parse::Object
67
- class Pointer < Model
68
- # The default attributes in a Parse Pointer hash.
69
- ATTRIBUTES = { __type: :string, className: :string, objectId: :string}.freeze
70
- # @return [String] the name of the Parse class for this pointer.
71
- attr_accessor :parse_class
72
- # @return [String] the objectId field
73
- attr_accessor :id
74
-
75
- # @return [Model::TYPE_POINTER]
76
- def __type; Parse::Model::TYPE_POINTER; end;
77
- alias_method :className, :parse_class
78
- # A Parse object as a className field and objectId. In ruby, we will use the
79
- # id attribute method, but for usability, we will also alias it to objectId
80
- alias_method :objectId, :id
81
-
82
- # A Parse pointer only requires the name of the remote Parse collection name,
83
- # and the `objectId` of the record.
84
- # @param table [String] The Parse class name in the Parse database.
85
- # @param oid [String] The objectId
86
- def initialize(table, oid)
87
- @parse_class = table.to_s
88
- @id = oid.to_s
89
- end
13
+ # The Pointer class represents the pointer type in Parse and is the superclass
14
+ # of Parse::Object types. A pointer can be considered a type of Parse::Object
15
+ # in which only the class name and id is known. In most cases, you may not
16
+ # deal with Parse::Pointer objects directly if you have defined all your
17
+ # Parse::Object subclasses.
18
+ #
19
+ # A `Parse::Pointer` only contains data about the specific Parse class and
20
+ # the `id` for the object. Therefore, creating an instance of any
21
+ # Parse::Object subclass with only the `:id` field set will be
22
+ # considered in "pointer" state even though its specific class is not
23
+ # `Parse::Pointer` type. The only case that you may have a Parse::Pointer
24
+ # is in the case where an object was received for one of your classes and
25
+ # the framework has no registered class handler for it.
26
+ # Assume you have the tables `Post`, `Comment` and `Author` defined in your
27
+ # remote Parse database, but have only defined `Post` and `Commentary`
28
+ # locally.
29
+ # @example
30
+ # class Post < Parse::Object
31
+ # end
32
+ #
33
+ # class Commentary < Parse::Object
34
+ # belongs_to :post
35
+ # belongs_to :author
36
+ # end
37
+ #
38
+ # comment = Commentary.first
39
+ # comment.post? # true because it is non-nil
40
+ # comment.artist? # true because it is non-nil
41
+ #
42
+ # # both are true because they are in a Pointer state
43
+ # comment.post.pointer? # true
44
+ # comment.author.pointer? # true
45
+ #
46
+ # # we have defined a Post class handler
47
+ # comment.post # <Post @parse_class="Post", @id="xdqcCqfngz">
48
+ #
49
+ # # we have not defined an Author class handler
50
+ # comment.author # <Parse::Pointer @parse_class="Author", @id="hZLbW6ofKC">
51
+ #
52
+ #
53
+ # comment.post.fetch # fetch the relation
54
+ # comment.post.pointer? # false, it is now a full object.
55
+ #
56
+ # The effect is that for any unknown classes that the framework encounters,
57
+ # it will generate Parse::Pointer instances until you define those classes
58
+ # with valid properties and associations. While this might be ok for some
59
+ # classes you do not use, we still recommend defining all your Parse classes
60
+ # locally in the framework.
61
+ #
62
+ # Once you have a subclass, you may also create a Parse::Pointer object using
63
+ # the _pointer_ method.
64
+ # @example
65
+ # Parse::User.pointer("123456") # => Parse::Pointer for "_User" class
66
+ #
67
+ # @see Parse::Object
68
+ class Pointer < Model
69
+ # The default attributes in a Parse Pointer hash.
70
+ ATTRIBUTES = { __type: :string, className: :string, objectId: :string }.freeze
71
+ # @return [String] the name of the Parse class for this pointer.
72
+ attr_accessor :parse_class
73
+ # @return [String] the objectId field
74
+ attr_accessor :id
75
+
76
+ # @return [Model::TYPE_POINTER]
77
+ def __type; Parse::Model::TYPE_POINTER; end
78
+
79
+ alias_method :className, :parse_class
80
+ # A Parse object as a className field and objectId. In ruby, we will use the
81
+ # id attribute method, but for usability, we will also alias it to objectId
82
+ alias_method :objectId, :id
83
+
84
+ # A Parse pointer only requires the name of the remote Parse collection name,
85
+ # and the `objectId` of the record.
86
+ # @param table [String] The Parse class name in the Parse database.
87
+ # @param oid [String] The objectId
88
+ def initialize(table, oid)
89
+ @parse_class = table.to_s
90
+ @id = oid.to_s
91
+ end
90
92
 
91
- # @return [String] the name of the collection for this Pointer.
92
- def parse_class
93
- @parse_class
94
- end
93
+ # @return [String] the name of the collection for this Pointer.
94
+ def parse_class
95
+ @parse_class
96
+ end
95
97
 
96
- # @return [String] a string representing the class and id of this instance.
97
- def sig
98
- "#{@parse_class}##{id || 'new'}"
99
- end
98
+ # @return [String] a string representing the class and id of this instance.
99
+ def sig
100
+ "#{@parse_class}##{id || "new"}"
101
+ end
100
102
 
101
- # @return [Hash]
102
- def attributes
103
- ATTRIBUTES
104
- end
103
+ # @return [Hash]
104
+ def attributes
105
+ ATTRIBUTES
106
+ end
105
107
 
106
- # @return [Hash] serialized JSON structure
107
- def json_hash
108
- JSON.parse to_json
109
- end
108
+ # @return [Hash] serialized JSON structure
109
+ def json_hash
110
+ JSON.parse to_json
111
+ end
110
112
 
111
- # Create a new pointer with the current class name and id. While this may not make sense
112
- # for a pointer instance, Parse::Object subclasses use this inherited method to turn themselves into
113
- # pointer objects.
114
- # @example
115
- # user = Parse::User.first
116
- # user.pointer # => Parse::Pointer("_User", user.id)
117
- #
118
- # @return [Pointer] a new Pointer for this object.
119
- # @see Parse::Object
120
- def pointer
121
- Pointer.new parse_class, @id
122
- end
113
+ # Create a new pointer with the current class name and id. While this may not make sense
114
+ # for a pointer instance, Parse::Object subclasses use this inherited method to turn themselves into
115
+ # pointer objects.
116
+ # @example
117
+ # user = Parse::User.first
118
+ # user.pointer # => Parse::Pointer("_User", user.id)
119
+ #
120
+ # @return [Pointer] a new Pointer for this object.
121
+ # @see Parse::Object
122
+ def pointer
123
+ Pointer.new parse_class, @id
124
+ end
123
125
 
124
- # Whether this instance is in pointer state. A pointer is determined
125
- # if we have a parse class and an id, but no created_at or updated_at fields.
126
- # @return [Boolean] true if instance is in pointer state.
127
- def pointer?
128
- present? && @created_at.blank? && @updated_at.blank?
129
- end
126
+ # Whether this instance is in pointer state. A pointer is determined
127
+ # if we have a parse class and an id, but no created_at or updated_at fields.
128
+ # @return [Boolean] true if instance is in pointer state.
129
+ def pointer?
130
+ present? && @created_at.blank? && @updated_at.blank?
131
+ end
130
132
 
131
- # Returns true if the data for this instance has been fetched. Because of some autofetching
132
- # mechanisms, this is useful to know whether the object already has data without actually causing
133
- # a fetch of the data.
134
- # @return [Boolean] true if not in pointer state.
135
- def fetched?
136
- present? && pointer? == false
137
- end
133
+ # Returns true if the data for this instance has been fetched. Because of some autofetching
134
+ # mechanisms, this is useful to know whether the object already has data without actually causing
135
+ # a fetch of the data.
136
+ # @return [Boolean] true if not in pointer state.
137
+ def fetched?
138
+ present? && pointer? == false
139
+ end
138
140
 
139
- # This method is a general implementation that gets overriden by Parse::Object subclass.
140
- # Given the class name and the id, we will go to Parse and fetch the actual record, returning the
141
- # JSON object.
142
- # @return [Parse::Object] the fetched Parse::Object, nil otherwise.
143
- def fetch
144
- response = client.fetch_object(parse_class, id)
145
- return nil if response.error?
146
- response.result
147
- end
141
+ # This method is a general implementation that gets overriden by Parse::Object subclass.
142
+ # Given the class name and the id, we will go to Parse and fetch the actual record, returning the
143
+ # JSON object.
144
+ # @return [Parse::Object] the fetched Parse::Object, nil otherwise.
145
+ def fetch
146
+ response = client.fetch_object(parse_class, id)
147
+ return nil if response.error?
148
+ response.result
149
+ end
148
150
 
149
- # Two Parse::Pointers (or Parse::Objects) are equal if both of them have
150
- # the same Parse class and the same id.
151
- # @return [Boolean]
152
- def ==(o)
153
- return false unless o.is_a?(Pointer)
154
- #only equal if the Parse class and object ID are the same.
155
- self.parse_class == o.parse_class && id == o.id
156
- end
157
- alias_method :eql?, :==
158
-
159
- # Compute a hash-code for this object. It is calculated
160
- # by combining the Parse class name, the {Parse::Object#id} field and
161
- # any pending changes.
162
- #
163
- # Two objects with the same content will have the same hash code
164
- # (and will compare using eql?).
165
- # @return [Fixnum]
166
- def hash
167
- "#{parse_class}#{id}#{changes.to_s}".hash
168
- end
151
+ # Two Parse::Pointers (or Parse::Objects) are equal if both of them have
152
+ # the same Parse class and the same id.
153
+ # @return [Boolean]
154
+ def ==(o)
155
+ return false unless o.is_a?(Pointer)
156
+ #only equal if the Parse class and object ID are the same.
157
+ self.parse_class == o.parse_class && id == o.id
158
+ end
169
159
 
170
- # @return [Boolean] true if instance has a Parse class and an id.
171
- def present?
172
- parse_class.present? && @id.present?
173
- end
160
+ alias_method :eql?, :==
174
161
 
175
- # Access the pointer properties through hash accessor. This is done for
176
- # compatibility with the hash access of a Parse::Object. This method
177
- # returns nil if the key is not one of: :id, :objectId, or :className.
178
- # @param key [String] the name of the property.
179
- # @return [Object] the value for this key.
180
- def [](key)
181
- return nil unless [:id,:objectId,:className].include?(key.to_sym)
182
- send(key)
183
- end
162
+ # Compute a hash-code for this object. It is calculated
163
+ # by combining the Parse class name, the {Parse::Object#id} field and
164
+ # any pending changes.
165
+ #
166
+ # Two objects with the same content will have the same hash code
167
+ # (and will compare using eql?).
168
+ # @return [Fixnum]
169
+ def hash
170
+ "#{parse_class}#{id}#{changes.to_s}".hash
171
+ end
184
172
 
185
- # Set the pointer properties through hash accessor. This is done for
186
- # compatibility with the hash access of a Parse::Object. This method
187
- # does nothing if the key is not one of: :id, :objectId, or :className.
188
- # @param key (see #[])
189
- # @return [Object]
190
- def []=(key,value)
191
- return unless [:id,:objectId,:className].include?(key.to_sym)
192
- send("#{key}=",value)
193
- end
173
+ # @return [Boolean] true if instance has a Parse class and an id.
174
+ def present?
175
+ parse_class.present? && @id.present?
176
+ end
194
177
 
178
+ # Access the pointer properties through hash accessor. This is done for
179
+ # compatibility with the hash access of a Parse::Object. This method
180
+ # returns nil if the key is not one of: :id, :objectId, or :className.
181
+ # @param key [String] the name of the property.
182
+ # @return [Object] the value for this key.
183
+ def [](key)
184
+ return nil unless [:id, :objectId, :className].include?(key.to_sym)
185
+ send(key)
195
186
  end
196
187
 
188
+ # Set the pointer properties through hash accessor. This is done for
189
+ # compatibility with the hash access of a Parse::Object. This method
190
+ # does nothing if the key is not one of: :id, :objectId, or :className.
191
+ # @param key (see #[])
192
+ # @return [Object]
193
+ def []=(key, value)
194
+ return unless [:id, :objectId, :className].include?(key.to_sym)
195
+ send("#{key}=", value)
196
+ end
197
+ end
197
198
  end
198
199
 
199
200
  # extensions
@@ -1,9 +1,10 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative '../query.rb'
5
- require_relative '../client.rb'
6
- require 'active_model_serializers'
4
+ require_relative "../query.rb"
5
+ require_relative "../client.rb"
6
+ require "active_model_serializers"
7
+
7
8
  module Parse
8
9
  # This class represents the API to send push notification to devices that are
9
10
  # available in the Installation table. Push notifications are implemented
@@ -68,7 +69,7 @@ module Parse
68
69
  # @!attribute [rw] channels
69
70
  # @return [Array] an array of strings for subscribed channels.
70
71
  attr_accessor :query, :alert, :badge, :sound, :title, :data,
71
- :expiration_time, :expiration_interval, :push_time, :channels
72
+ :expiration_time, :expiration_interval, :push_time, :channels
72
73
 
73
74
  alias_method :message, :alert
74
75
  alias_method :message=, :alert=
@@ -134,14 +135,13 @@ module Parse
134
135
  msg = {
135
136
  data: {
136
137
  alert: alert,
137
- badge: badge || "Increment"
138
- }
138
+ badge: badge || "Increment",
139
+ },
139
140
  }
140
141
  msg[:data][:sound] = sound if sound.present?
141
142
  msg[:data][:title] = title if title.present?
142
143
  msg[:data].merge! @data if @data.is_a?(Hash)
143
144
 
144
-
145
145
  if @expiration_time.present?
146
146
  msg[:expiration_time] = @expiration_time.respond_to?(:iso8601) ? @expiration_time.iso8601(3) : @expiration_time
147
147
  end
@@ -170,9 +170,7 @@ module Parse
170
170
  def send(message = nil)
171
171
  @alert = message if message.is_a?(String)
172
172
  @data = message if message.is_a?(Hash)
173
- client.push( payload.as_json )
173
+ client.push(payload.as_json)
174
174
  end
175
-
176
175
  end
177
-
178
176
  end
@@ -1,5 +1,4 @@
1
-
2
- require_relative 'object'
1
+ require_relative "object"
3
2
 
4
3
  # Simple include to use short verion of core class names
5
4
  ::Installation = Parse::Installation unless defined?(::Installation)
@@ -1,8 +1,8 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'active_support'
5
- require 'active_support/values/time_zone'
4
+ require "active_support"
5
+ require "active_support/values/time_zone"
6
6
  require_relative "model"
7
7
 
8
8
  module Parse
@@ -118,7 +118,7 @@ module Parse
118
118
  @name = timezone
119
119
  @zone = nil
120
120
  else
121
- raise ArgumentError, 'Invalid value passed to Parse::TimeZone#zone.'
121
+ raise ArgumentError, "Invalid value passed to Parse::TimeZone#zone."
122
122
  end
123
123
  end
124
124
 
@@ -137,7 +137,5 @@ module Parse
137
137
  def valid?
138
138
  ActiveSupport::TimeZone[to_s].present?
139
139
  end
140
-
141
140
  end
142
-
143
141
  end