parse-stack 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9f0d4895395a8d71c15ada27009a1176791a1604
4
- data.tar.gz: c9bac3568ea1963c7972b4a32013a7d322324681
3
+ metadata.gz: 2a515a094fadb46b58f8acbefd80f8188e265b22
4
+ data.tar.gz: 64702d47c7a395c9ae754374aa9cf8b9fec048a4
5
5
  SHA512:
6
- metadata.gz: 0256eee4e1a40e2f3ad3eb6918a4875d4bd1fe2a3a034e4bbbe0e1bd16bebeb465a886859c490a267b7298e64492c164c4fa2c0f3a67be4c8ec599d4e5c47b7e
7
- data.tar.gz: d8ac611c347806df930d7a1a5ba75530dc94268d5425ef970aba6db5efc7df2c57026c13f0356b5ebdc5388edabea90a64a785359982a5a0ee2186697c3643e4
6
+ metadata.gz: 8402485e10d774c12325542f3a4aabcf24a10f7626a6dc1d32b76f47df9283408a796e5440642d6f84b0a58ebf777637a77fa94cb52e78f5027ae0a625fdd2c8
7
+ data.tar.gz: e080d1f9665dd80694eb5802162ab67a0b6bd72f8b8c6b9e4b8e0aa1ed348ce5c5dbceb21c89f1355b5769c4021fe7067458bef624e34caeb388da67da15e1c3
data/Changes.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # Parse-Stack Changes
2
2
 
3
+ 1.3.0
4
+ -----------
5
+ - **IMPORTANT**: __Raising an error no longer sends an error response back to
6
+ the client in a Webhook trigger. You must now call `error!('...')` instead of
7
+ calling `raise '...'`.__ The webhook block is now binded to the Parse::Payload
8
+ instance, removing the need to pass `payload` object; use the instance methods directly.
9
+ See updated README.md for more details.
10
+ - **Parse-Stack will throw new exceptions** depending on the error code returned by Parse. These
11
+ are of type AuthenticationError, TimeoutError, ProtocolError, ServerError, ConnectionError and RequestLimitExceededError.
12
+ - `nil` and Delete operations for `:integers` and `:booleans` are no longer typecast.
13
+ - Added aliases `before`, `on_or_before`, `after` and `on_or_after` to help with
14
+ comparing non-integer fields such as dates. These map to `lt`,`lte`, `gt` and `gte`.
15
+ - Schema API return true is no changes were made to the table on `auto_upgrade!` (success)
16
+ - Parse::Middleware::Caching no longer caches 404 and 410 responses; and responses
17
+ with content lengths less than 20 bytes.
18
+ - FIX: Parse::Payload when applying auth_data in Webhooks. This fixes handing Facebook
19
+ login with Android devices.
20
+ - New method `save!` to raise an exception if the save fails.
21
+ - FIX: Verify Content-Type header field is present for webhooks before checking its value.
22
+ - FIX: Support `reload!` when using it Padrino.
23
+
3
24
  1.2.1
4
25
  -----------
5
26
  - Add active support string dependencies.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parse-stack (1.2.1)
4
+ parse-stack (1.3.0)
5
5
  active_model_serializers (>= 0.9, < 1)
6
6
  activemodel (>= 4.2.1, < 5)
7
7
  activesupport (>= 4.2.1, < 5)
@@ -114,4 +114,4 @@ DEPENDENCIES
114
114
  rake (~> 10)
115
115
 
116
116
  BUNDLED WITH
117
- 1.11.2
117
+ 1.12.5
data/README.md CHANGED
@@ -116,7 +116,7 @@ song.likes.add Parse::User.first(username: "persaud")
116
116
  song.save
117
117
 
118
118
  # find songs
119
- songs = Song.all(artist: artist, :plays.gt => 100, :released.lte => 10.years.ago)
119
+ songs = Song.all(artist: artist, :plays.gt => 100, :released.on_or_after => 30.days.ago)
120
120
 
121
121
  songs.each { |s| s.tags.add "awesome" }
122
122
  # batch saves
@@ -125,9 +125,6 @@ songs.save
125
125
  # Call Cloud Code functions
126
126
  result = Parse.call_function :myFunctionName, {param: value}
127
127
 
128
- # Trigger a Parse Job
129
- Parse.trigger_job :myBackgroundJob, {param: value}
130
-
131
128
  ```
132
129
 
133
130
  ## Main Features
@@ -138,7 +135,7 @@ While there are many additional features of the framework, these are the main po
138
135
  - Queries support with caching middleware. (Reduces API usage)
139
136
  - Support for all Parse data types.
140
137
  - One-to-One, One-to-Many and Many-to-Many relations.
141
- - Inegration with Parse Cloud Code Webhooks.
138
+ - Integration with Parse Cloud Code Webhooks.
142
139
  - Send Push notifications with advanced targeting.
143
140
  - Schema upgrades and migrations.
144
141
 
@@ -565,12 +562,15 @@ end
565
562
  ```
566
563
 
567
564
  #### Raising an exception when save fails
568
- By default, we return `true` or `false` for save and destroy operations. If you prefer to have `Parse::Object` raise an exception instead, you can tell to do so either globally or on a per-model basis.
565
+ By default, we return `true` or `false` for save and destroy operations. If you prefer to have `Parse::Object` raise an exception instead, you can tell to do so either globally or on a per-model basis. When a save fails, it will raise a `Parse::SaveFailureError`.
569
566
 
570
567
  ```ruby
571
568
  Parse::Model.raise_on_save_failure = true # globally across all models
572
569
  Song.raise_on_save_failure = true # per-model
573
570
 
571
+ # or per-instance raise on failure
572
+ song.save!
573
+
574
574
  ```
575
575
 
576
576
  When enabled, if an error is returned by Parse due to saving or destroying a record, due to your `before_save` or `before_delete` validation cloud code triggers, `Parse::Object` will return the a `Parse::SaveFailureError` exception type. This exception has an instance method of `#object` which contains the object that failed to save.
@@ -579,7 +579,7 @@ When enabled, if an error is returned by Parse due to saving or destroying a rec
579
579
  To create a new object you can call `#new` while passing a hash of attributes you want to set. You can then use the property accessors to also modify individual properties. As you modify properties, you can access dirty tracking state and data using the generated [`ActiveModel::Dirty`](http://api.rubyonrails.org/classes/ActiveModel/Dirty.html) features. When you are ready to commit the new object to Parse, you can call `#save`.
580
580
 
581
581
  ```ruby
582
- song = Song.new(name: "My Old Song")
582
+ song = Song.new name: "My Old Song"
583
583
  song.new? # true
584
584
  song.id # nil
585
585
  song.released = DateTime.now
@@ -744,7 +744,7 @@ You can destroy a Parse record, just call the `#destroy` method. It will return
744
744
  song.destroy
745
745
 
746
746
  # or in a batch
747
- songs = Song.all(:limit => 10)
747
+ songs = Song.all :limit => 10
748
748
  songs.destroy # uses batch operation
749
749
  ```
750
750
 
@@ -973,15 +973,23 @@ Most of the constraints supported by Parse are available to `Parse::Query`. Assu
973
973
 
974
974
  # less than
975
975
  q.where :field.lt => value
976
+ # alias to `lt`; useful when dealing with dates
977
+ q.where :field.before => value
976
978
 
977
979
  # less than or equal to
978
980
  q.where :field.lte => value
981
+ # alias to `lte`; useful when dealing with dates
982
+ q.where :field.on_or_before => value
979
983
 
980
984
  # greater than
981
985
  q.where :field.gt => value
986
+ # alias to `gt`; useful when dealing with dates
987
+ q.where :field.after => value
982
988
 
983
989
  # greater than or equal to
984
990
  q.where :field.gte => value
991
+ # alias to `gte`; useful when dealing with dates
992
+ q.where :field.on_or_after => value
985
993
 
986
994
  # Not equal to
987
995
  q.where :field.not => value
@@ -1109,19 +1117,17 @@ Push notifications are implemented through the `Parse::Push` class. To send push
1109
1117
  Parse Parse allows you to receive Cloud Code webhooks on your own hosted server. The `Parse::Webhooks` class is a lightweight Rack application that routes incoming Cloud Code webhook requests and payloads to locally registered handlers. The payloads are `Parse::Payload` type of objects that represent that data that Parse sends webhook handlers. You can register any of the Cloud Code webhook trigger hooks (`beforeSave`, `afterSave`, `beforeDelete`, `afterDelete`) and function hooks.
1110
1118
 
1111
1119
  ### Setup Cloud Code functions
1112
- You can use the `route()` method to register handler blocks.
1113
-
1114
- If a function block returns any value that is true for `blank?`, we will automatically return `true` as part of the response to the webhook. If an exception is raised inside the block, we will return the correct Parse error response with the value you provided.
1120
+ You can use the `route()` method to register handler blocks. The last value returned by the block will be returned back to the client in a success response. If `error!(value)` is called inside the block, we will return the correct Parse error response with the value you provided.
1115
1121
 
1116
1122
  ```ruby
1117
1123
  # Register handling the 'helloWorld' function.
1118
- Parse::Webhooks.route(:function, :helloWorld) do |payload|
1119
- # use the Parse::Payload payload object
1120
- params = payload.params #function params
1124
+ Parse::Webhooks.route(:function, :helloWorld) do
1125
+ # use the Parse::Payload instance methods in this block
1126
+ incoming_params = params #function params
1121
1127
  name = params['name'].to_s
1122
1128
 
1123
1129
  # will return proper error response
1124
- raise "Missing argument 'name'." unless name.present?
1130
+ error!("Missing argument 'name'.") unless name.present?
1125
1131
  # return early
1126
1132
  "Hello #{name}!"
1127
1133
  end
@@ -1135,9 +1141,9 @@ If you are creating `Parse::Object` subclasses, you may also register them there
1135
1141
  ```ruby
1136
1142
  class Song < Parse::Object
1137
1143
 
1138
- webhook :function, :mySongFunction do |payload|
1139
- user = payload.user
1140
- params = payload.params
1144
+ webhook :function, :mySongFunction do
1145
+ the_user = user # available if a Parse user made the call
1146
+ params = params
1141
1147
  # ... do stuff ...
1142
1148
  true
1143
1149
  end
@@ -1147,7 +1153,7 @@ end
1147
1153
  ```
1148
1154
 
1149
1155
  ### Setup Cloud Code Triggers
1150
- You can register webhooks to handle the different object triggers: `:before_save`, `:after_save`, `:before_delete` and `:after_delete`. While you can use `Parse::Webhooks.route` to register the trigger, we recommend keeping the code inside you model. The `payload` object, which is an instance of `Parse::Payload`
1156
+ You can register webhooks to handle the different object triggers: `:before_save`, `:after_save`, `:before_delete` and `:after_delete`. The `payload` object, which is an instance of `Parse::Payload`, contains several properties that represent the payload. One of the most important ones is `parse_object`, which will provide you with the instance of your specific Parse object. In `:before_save` triggers, this object already contains dirty tracking information of what has been changed.
1151
1157
 
1152
1158
  ```ruby
1153
1159
  # recommended way
@@ -1155,23 +1161,25 @@ You can register webhooks to handle the different object triggers: `:before_save
1155
1161
  # ... properties ...
1156
1162
 
1157
1163
  # setup after save for Artist
1158
- webhook :after_save do |payload|
1159
- user = payload.user # Parse::User
1160
- artist = payload.parse_object # Artist
1164
+ webhook :after_save do
1165
+ puts "User: #{user.username}" if user.present? # Parse::User
1166
+ artist = parse_object # Artist
1167
+ # no need for return in after save
1161
1168
  end
1162
1169
 
1163
1170
  end
1164
1171
 
1165
1172
  # or the explicit way
1166
- Parse::Webhooks.route :after_save, "Artist" do |payload|
1167
- user = payload.user # Parse::User
1168
- artist = payload.parse_object # Artist
1173
+ Parse::Webhooks.route :after_save, "Artist" do
1174
+ puts "User: #{user.username}" if user.present? # Parse::User
1175
+ artist = parse_object # Artist
1176
+ # no need for return in after save
1169
1177
  end
1170
1178
  ```
1171
1179
 
1172
1180
  For any `after_*` hook, return values are not needed since Parse does not utilize them. You may also register as many `after_save` or `after_delete` handlers as you prefer, all of them will be called.
1173
1181
 
1174
- `before_save` and `before_delete` hooks have special functionality. When an exception is thrown inside the provided block, the framework will return the correct error response to Parse with value provided to raise. Returning an error will prevent Parse from saving the object in the case of `before_save` and will prevent Parse from deleting the object when in a `before_delete`. In addition, for a `before_save`, the last value returned by the block will be the value returned in the success response. If the block returns nil or an `empty?` value, it will return `true` as the default response. You can also return a JSON object in a hash format to override the values that will be saved for the object. For more details, see [Cloud Code BeforeSave Webhooks](https://parse.com/docs/cloudcode/guide#cloud-code-advanced-beforesave-webhooks)
1182
+ `before_save` and `before_delete` hooks have special functionality. When the `error!` method is called by the provided block, the framework will return the correct error response to Parse with value provided. Returning an error will prevent Parse from saving the object in the case of `before_save` and will prevent Parse from deleting the object when in a `before_delete`. In addition, for a `before_save`, the last value returned by the block will be the value returned in the success response. If the block returns nil or an `empty?` value, it will return `true` as the default response. You can also return a JSON object in a hash format to override the values that will be saved for the object. For this, we recommend using the `payload_update` method. For more details, see [Cloud Code BeforeSave Webhooks](https://parse.com/docs/cloudcode/guide#cloud-code-advanced-beforesave-webhooks)
1175
1183
 
1176
1184
  ```ruby
1177
1185
  # recommended way
@@ -1180,9 +1188,9 @@ class Artist < Parse::Object
1180
1188
  property :location, :geopoint
1181
1189
 
1182
1190
  # setup after save for Artist
1183
- webhook :before_save do |payload|
1184
- user = payload.user # Parse::User
1185
- artist = payload.parse_object # Artist
1191
+ webhook :before_save do
1192
+ the_user = user # Parse::User
1193
+ artist = parse_object # Artist
1186
1194
  # artist object will have dirty tracking information
1187
1195
 
1188
1196
  artist.new? # true if this is a new object
@@ -1191,19 +1199,19 @@ class Artist < Parse::Object
1191
1199
  artist.location ||= Parse::GeoPoint.new(32.82, -117.23)
1192
1200
 
1193
1201
  # raise to fail the save
1194
- raise "Name cannot be empty" if artist.name.blank?
1202
+ error!("Name cannot be empty") if artist.name.blank?
1195
1203
 
1196
1204
  if artist.name_changed?
1197
1205
  # .. do something if `name` has changed
1198
1206
  end
1199
1207
 
1200
- # return a special hash of changed values
1208
+ # *important* returns a special hash of changed values
1201
1209
  artist.payload_update
1202
1210
  end
1203
1211
 
1204
- webhook :before_delete do |payload|
1212
+ webhook :before_delete do
1205
1213
  # prevent deleting Artist records
1206
- raise "You can't delete an Artist"
1214
+ error!("You can't delete an Artist")
1207
1215
  end
1208
1216
 
1209
1217
  end
@@ -1323,7 +1331,7 @@ same_user = Parse::User.first # cached result
1323
1331
  Add this line to your application's Gemfile:
1324
1332
 
1325
1333
  ```ruby
1326
- gem 'parse-stack'
1334
+ gem 'parse-stack', require: 'parse/stack'
1327
1335
  ```
1328
1336
 
1329
1337
  or install it locally
@@ -12,6 +12,11 @@ module Parse
12
12
 
13
13
  # This is an exception that is thrown if there is a client connectivity issue
14
14
  class ConnectionError < Exception; end;
15
+ class TimeoutError < Exception; end;
16
+ class ProtocolError < Exception; end;
17
+ class ServerError < Exception; end;
18
+ class AuthenticationError < Exception; end;
19
+ class RequestLimitExceededError < Exception; end;
15
20
 
16
21
  # Main class for the client. The client class is based on a Faraday stack.
17
22
  # The Faraday stack is similar to a Rack-style application in which you can define middlewares
@@ -153,7 +158,42 @@ module Parse
153
158
  params = (method == :get ? query : body) || {}
154
159
  # if the path does not start with the '/1/' prefix, then add it to be nice.
155
160
  # actually send the request and return the body
156
- @session.send(method, uri, params, headers).body
161
+ response = @session.send(method, uri, params, headers)
162
+ body = response.body
163
+
164
+ case response.status
165
+ when 401, 403
166
+ puts "[ParseError] #{body}"
167
+ raise Parse::AuthenticationError, body
168
+ when 400, 408
169
+ puts "[ParseError] #{body}"
170
+ if body.code == 124 || body.code == 143 #"net/http: timeout awaiting response headers"
171
+ raise Parse::TimeoutError, body
172
+ end
173
+ when 404
174
+ unless body.object_not_found?
175
+ puts "[ParseError] #{body}"
176
+ raise Parse::ConnectionError, body
177
+ end
178
+ when 405, 406
179
+ puts "[ParseError] #{body}"
180
+ raise Parse::ProtocolError, body
181
+ when 500
182
+ puts "[ParseError] #{body}"
183
+ raise Parse::ServerError, body
184
+ end
185
+
186
+ if body.error?
187
+ if body.code <= 100
188
+ puts "[ParseError] #{body}"
189
+ raise Parse::ServerError, body
190
+ elsif body.code == 155
191
+ puts "[ParseError] #{body}"
192
+ raise Parse::RequestLimitExceededError, body
193
+ end
194
+ end
195
+
196
+ body
157
197
  rescue Faraday::Error::ClientError => e
158
198
  raise Parse::ConnectionError, e.message
159
199
  end
@@ -13,9 +13,9 @@ module Parse
13
13
  # * 300 - 'Multiple Choices'
14
14
  # * 301 - 'Moved Permanently'
15
15
  # * 302 - 'Found'
16
- # * 404 - 'Not Found'
17
- # * 410 - 'Gone'
18
- CACHEABLE_HTTP_CODES = [200, 203, 300, 301, 302, 404, 410].freeze
16
+ # * 404 - 'Not Found' - removed
17
+ # * 410 - 'Gone' - removed
18
+ CACHEABLE_HTTP_CODES = [200, 203, 300, 301, 302].freeze
19
19
 
20
20
  class << self
21
21
  attr_accessor :enabled, :logging
@@ -88,10 +88,14 @@ module Parse
88
88
 
89
89
 
90
90
  @app.call(env).on_complete do |response_env|
91
- # Only cache GET requests with valid HTTP status codes.
92
- if cache_enabled && method == :get && CACHEABLE_HTTP_CODES.include?(response_env.status) && response_env.present?
93
- @store.store(url, response_env, expires: @expires) # ||= response_env.body
94
- end
91
+ # Only cache GET requests with valid HTTP status codes whose content-length
92
+ # is greater than 20. Otherwise they could be errors, successes and empty result sets.
93
+ if cache_enabled && method == :get && CACHEABLE_HTTP_CODES.include?(response_env.status) &&
94
+ response_env.present? && response_env.response_headers["content-length".freeze].to_i > 20
95
+
96
+ @store.store(url, response_env, expires: @expires) # ||= response_env.body
97
+
98
+ end # if
95
99
  # do something with the response
96
100
  # response_env[:response_headers].merge!(...)
97
101
  end
@@ -3,13 +3,14 @@ require 'active_support/json'
3
3
  # be a set of responses (from a Batch response).
4
4
  module Parse
5
5
 
6
+
6
7
  class Response
7
8
  include Enumerable
8
9
 
9
10
  ERROR_INTERNAL = 1
10
11
  ERROR_TIMEOUT = 124
11
12
  ERROR_EXCEEDED_BURST_LIMIT = 155
12
- ERROR_OBJECT_NOT_FOUND_FOR_GET = 101
13
+ ERROR_OBJECT_NOT_FOUND = 101
13
14
 
14
15
  ERROR = "error".freeze
15
16
  CODE = "code".freeze
@@ -95,6 +96,10 @@ module Parse
95
96
  ! success?
96
97
  end
97
98
 
99
+ def object_not_found?
100
+ @code == ERROR_OBJECT_NOT_FOUND
101
+ end
102
+
98
103
  # returns the result data from the response. Always returns an array.
99
104
  def results
100
105
  return [] if @result.nil?
@@ -112,5 +117,18 @@ module Parse
112
117
  self
113
118
  end
114
119
 
120
+ def inspect
121
+ if error?
122
+ "#<#{self.class} @code=#{code} @error='#{error}'>"
123
+ else
124
+ "#<#{self.class} @result='#{@result}'>"
125
+ end
126
+ end
127
+
128
+ def to_s
129
+ return "E-#{@code}: #{@error}" if error?
130
+ @result
131
+ end
132
+
115
133
  end
116
134
  end
@@ -280,7 +280,8 @@ module Parse
280
280
  # saves the object. If the object has not changed, it is a noop. If it is new,
281
281
  # we will create the object. If the object has an id, we will update the record.
282
282
  # You can define before and after :save callbacks
283
- def save
283
+ # autoraise: set to true will automatically raise an exception if the save fails
284
+ def save(autoraise: false)
284
285
  return true unless changed?
285
286
  success = false
286
287
  run_callbacks :save do
@@ -298,13 +299,13 @@ module Parse
298
299
  success = update_relations
299
300
  if success
300
301
  changes_applied!
301
- elsif self.class.raise_on_save_failure
302
+ elsif self.class.raise_on_save_failure || autoraise.present?
302
303
  raise Parse::SaveFailureError.new(self), "Failed updating relations. #{self.parse_class} partially saved."
303
304
  end
304
305
  else
305
306
  changes_applied!
306
307
  end
307
- elsif self.class.raise_on_save_failure
308
+ elsif self.class.raise_on_save_failure || autoraise.present?
308
309
  raise Parse::SaveFailureError.new(self), "Failed to create or save attributes. #{self.parse_class} was not saved."
309
310
  end
310
311
 
@@ -312,6 +313,11 @@ module Parse
312
313
  success
313
314
  end
314
315
 
316
+ # shortcut for raising an exception of saving this object failed.
317
+ def save!
318
+ save(autoraise: true)
319
+ end
320
+
315
321
  # only destroy the object if it has an id. You can setup before and after
316
322
  #callback hooks on :destroy
317
323
  def destroy
@@ -374,9 +374,17 @@ module Parse
374
374
  when :bytes
375
375
  val = Parse::Bytes.new(val) unless val.blank?
376
376
  when :integer
377
- val = val.to_i unless val.blank?
377
+ if val.nil? || val.respond_to?(:to_i) == false
378
+ val = nil
379
+ else
380
+ val = val.to_i
381
+ end
378
382
  when :boolean
379
- val = val ? true : false
383
+ if val.nil?
384
+ val = nil
385
+ else
386
+ val = val ? true : false
387
+ end
380
388
  when :string
381
389
  val = val.to_s unless val.blank?
382
390
  when :float
@@ -73,7 +73,7 @@ module Parse
73
73
  h[k] = v if remote_fields[k.to_s].nil?
74
74
  h
75
75
  end
76
- return if current_schema[:fields].empty?
76
+ return true if current_schema[:fields].empty?
77
77
  return update_schema( current_schema )
78
78
  else
79
79
  return create_schema
@@ -78,6 +78,11 @@ module Parse
78
78
  def self.registered_classes
79
79
  Parse::Object.descendants.map { |m| m.parse_class }.uniq
80
80
  end
81
+
82
+ # Find a corresponding class for this string or symbol
83
+ def self.classify(className)
84
+ Parse::Model.find_class className.to_parse_class
85
+ end
81
86
 
82
87
  class Object < Pointer
83
88
  include Properties
@@ -24,21 +24,25 @@ module Parse
24
24
  class LessOrEqualConstraint < Constraint
25
25
  contraint_keyword :$lte
26
26
  register :lte
27
+ register :on_or_before
27
28
  end
28
29
 
29
30
  class LessThanConstraint < Constraint
30
31
  contraint_keyword :$lt
31
32
  register :lt
33
+ register :before
32
34
  end
33
35
 
34
36
  class GreaterThanConstraint < Constraint
35
37
  contraint_keyword :$gt
36
38
  register :gt
39
+ register :after
37
40
  end
38
41
 
39
42
  class GreaterOrEqualConstraint < Constraint
40
43
  contraint_keyword :$gte
41
44
  register :gte
45
+ register :on_or_after
42
46
  end
43
47
 
44
48
  class NotEqualConstraint < Constraint
@@ -1,5 +1,5 @@
1
1
  module Parse
2
2
  module Stack
3
- VERSION = "1.2.1"
3
+ VERSION = "1.3.0"
4
4
  end
5
5
  end
@@ -80,18 +80,29 @@ module Parse
80
80
 
81
81
  end
82
82
 
83
+ class Payload
84
+ def error!(msg = "")
85
+ raise WebhookErrorResponse, msg
86
+ end
87
+ end
88
+
89
+ class WebhookErrorResponse < Exception; end;
83
90
  class Webhooks
84
91
 
92
+ def self.reload!(args = {})
93
+
94
+ end
95
+
85
96
  include Client::Connectable
86
97
  extend Webhook::Registration
87
98
 
88
99
  HTTP_PARSE_WEBHOOK = "HTTP_X_PARSE_WEBHOOK_KEY".freeze
89
100
  HTTP_PARSE_APPLICATION_ID = "HTTP_X_PARSE_APPLICATION_ID".freeze
90
101
  CONTENT_TYPE = "application/json".freeze
91
-
92
102
  attr_accessor :key
93
103
  class << self
94
104
  attr_accessor :logging
105
+
95
106
  def routes
96
107
  @routes ||= OpenStruct.new( {
97
108
  before_save: {}, after_save: {},
@@ -136,13 +147,10 @@ module Parse
136
147
  return unless routes[type].present? && routes[type][className].present?
137
148
  registry = routes[type][className]
138
149
 
139
- if registry.is_a?(Array)
140
- results = registry.map { |hook| hook.call(payload) }
141
- return results.last
142
- else
143
- return registry.call(payload)
144
- end
145
- nil
150
+ return payload.instance_exec(payload, &registry) unless registry.is_a?(Array)
151
+ results = registry.map { |hook| payload.instance_exec(payload, &hook) }
152
+ return results.last
153
+
146
154
  end
147
155
 
148
156
  def success(data = true)
@@ -167,7 +175,7 @@ module Parse
167
175
  return response.finish
168
176
  end
169
177
 
170
- unless request.content_type.include?(CONTENT_TYPE)
178
+ unless request.content_type.present? && request.content_type.include?(CONTENT_TYPE)
171
179
  response.write error("Invalid content-type format. Should be application/json.")
172
180
  return response.finish
173
181
  end
@@ -217,9 +225,12 @@ module Parse
217
225
  end
218
226
  response.write success(result)
219
227
  return response.finish
220
- rescue Exception => e
221
- puts "[ParseWebhooks Error] >> #{e}"
222
- puts e.backtrace
228
+ rescue Parse::WebhookErrorResponse => e
229
+ if payload.trigger?
230
+ puts "[Webhook ResponseError] >> #{payload.trigger_name} #{payload.parse_class}:#{payload.parse_id}: #{e}"
231
+ elsif payload.function?
232
+ puts "[Webhook ResponseError] >> #{payload.function_name}: #{e}"
233
+ end
223
234
  response.write error( e.to_s )
224
235
  return response.finish
225
236
  end
@@ -102,9 +102,16 @@ module Parse
102
102
  klass = Parse::Object.find_class parse_class
103
103
  # if we have a class, return that with updated changes, otherwise
104
104
  # default to regular object
105
- return klass.new(@object || {}) if klass.present?
106
- end
107
- end
105
+ if klass.present?
106
+ o = klass.new(@object || {})
107
+ if o.is_a?(Parse::User) && @update.present? && @update["authData"].present?
108
+ o.auth_data = @update["authData"]
109
+ end
110
+ return o
111
+ end # if klass.present?
112
+ end # if we have original
113
+
114
+ end # if before_trigger?
108
115
  Parse::Object.build(@object)
109
116
  end
110
117
 
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Anthony Persaud", "Mark Storch"]
10
10
  spec.email = ["persaud@modernistik.com", "mark_storch@yahoo.com"]
11
11
 
12
- spec.summary = %q{Parse Ruby Client SDK and Object Relational Mapping stack}
13
- spec.description = %q{A Parse Ruby Client, ORM, and Query engine to manage larger scale Parse applications}
12
+ spec.summary = %q{Parse SDK Ruby Client and Object Relational Mapping stack}
13
+ spec.description = %q{A Parse SDK Ruby Client, ORM, and Query engine to manage larger scale Parse applications}
14
14
  spec.homepage = "https://github.com/modernistik/parse-stack"
15
15
  spec.license = "MIT"
16
16
  # Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
@@ -25,6 +25,7 @@ Gem::Specification.new do |spec|
25
25
  spec.bindir = "exe"
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ["lib"]
28
+ spec.required_ruby_version = '>= 2.2'
28
29
 
29
30
  spec.add_runtime_dependency "activemodel", [">= 4.2.1", "< 5"]
30
31
  spec.add_runtime_dependency "activesupport", [">= 4.2.1", "< 5"]
@@ -41,5 +42,14 @@ Gem::Specification.new do |spec|
41
42
  spec.add_development_dependency "pry", "< 1"
42
43
  spec.add_development_dependency 'pry-stack_explorer', "< 1"
43
44
  spec.add_development_dependency 'pry-nav', "< 1"
45
+ spec.add_development_dependency 'dotenv', "< 3"
46
+ spec.post_install_message = <<UPGRADE
44
47
 
48
+ ** IMPORTANT **
49
+ Parse::Webhook exception handling has changed in 1.3.0. Please review Changes.md
50
+ and README.md for changes in webhooks functions and triggers.
51
+
52
+ See guide: https://github.com/modernistik/parse-stack/wiki/Webhook-Migration-1.2.x-to-1.3.0
53
+
54
+ UPGRADE
45
55
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parse-stack
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Persaud
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2016-06-22 00:00:00.000000000 Z
12
+ date: 2016-07-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -249,8 +249,22 @@ dependencies:
249
249
  - - "<"
250
250
  - !ruby/object:Gem::Version
251
251
  version: '1'
252
- description: A Parse Ruby Client, ORM, and Query engine to manage larger scale Parse
253
- applications
252
+ - !ruby/object:Gem::Dependency
253
+ name: dotenv
254
+ requirement: !ruby/object:Gem::Requirement
255
+ requirements:
256
+ - - "<"
257
+ - !ruby/object:Gem::Version
258
+ version: '3'
259
+ type: :development
260
+ prerelease: false
261
+ version_requirements: !ruby/object:Gem::Requirement
262
+ requirements:
263
+ - - "<"
264
+ - !ruby/object:Gem::Version
265
+ version: '3'
266
+ description: A Parse SDK Ruby Client, ORM, and Query engine to manage larger scale
267
+ Parse applications
254
268
  email:
255
269
  - persaud@modernistik.com
256
270
  - mark_storch@yahoo.com
@@ -322,7 +336,14 @@ homepage: https://github.com/modernistik/parse-stack
322
336
  licenses:
323
337
  - MIT
324
338
  metadata: {}
325
- post_install_message:
339
+ post_install_message: |2+
340
+
341
+ ** IMPORTANT **
342
+ Parse::Webhook exception handling has changed in 1.3.0. Please review Changes.md
343
+ and README.md for changes in webhooks functions and triggers.
344
+
345
+ See guide: https://github.com/modernistik/parse-stack/wiki/Webhook-Migration-1.2.x-to-1.3.0
346
+
326
347
  rdoc_options: []
327
348
  require_paths:
328
349
  - lib
@@ -330,7 +351,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
330
351
  requirements:
331
352
  - - ">="
332
353
  - !ruby/object:Gem::Version
333
- version: '0'
354
+ version: '2.2'
334
355
  required_rubygems_version: !ruby/object:Gem::Requirement
335
356
  requirements:
336
357
  - - ">="
@@ -341,5 +362,5 @@ rubyforge_project:
341
362
  rubygems_version: 2.5.1
342
363
  signing_key:
343
364
  specification_version: 4
344
- summary: Parse Ruby Client SDK and Object Relational Mapping stack
365
+ summary: Parse SDK Ruby Client and Object Relational Mapping stack
345
366
  test_files: []