angularjs-rails-resource 1.0.0.pre.3 → 1.0.0.pre.4
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 +4 -4
- data/CHANGELOG.md +34 -3
- data/README.md +98 -7
- data/bower.json +1 -1
- data/changelog.js +10 -1
- data/lib/angularjs-rails-resource/version.rb +1 -1
- data/package.json +1 -1
- data/test/unit/angularjs/rails/extensions/snapshotsSpec.js +0 -2
- data/test/unit/angularjs/rails/interceptorsSpec.js +413 -11
- data/test/unit/angularjs/rails/resourceSpec.js +19 -0
- data/test/unit/angularjs/rails/rootWrappingSpec.js +9 -24
- data/test/unit/angularjs/rails/transformersSpec.js +1 -2
- data/vendor/assets/javascripts/angularjs/rails/resource/extensions/snapshots.js +7 -4
- data/vendor/assets/javascripts/angularjs/rails/resource/resource.js +351 -115
- metadata +2 -2
@@ -478,6 +478,25 @@ describe('railsResourceFactory', function () {
|
|
478
478
|
$httpBackend.flush();
|
479
479
|
});
|
480
480
|
|
481
|
+
it('should not require query params on $delete', function () {
|
482
|
+
$httpBackend.expectDELETE('/test').respond(200);
|
483
|
+
Test.$delete('/test');
|
484
|
+
$httpBackend.flush();
|
485
|
+
});
|
486
|
+
|
487
|
+
it('should add query params passed to class $delete', function () {
|
488
|
+
$httpBackend.expectDELETE('/test?a=1').respond(200);
|
489
|
+
Test.$delete('/test', {a: 1});
|
490
|
+
$httpBackend.flush();
|
491
|
+
});
|
492
|
+
|
493
|
+
it('should add query params passed to instance $delete', function () {
|
494
|
+
var data = new Test({abcDef: 'xyz'});
|
495
|
+
|
496
|
+
$httpBackend.expectDELETE('/test?a=1').respond(200);
|
497
|
+
data.$delete('/test', {a: 1});
|
498
|
+
$httpBackend.flush();
|
499
|
+
});
|
481
500
|
});
|
482
501
|
|
483
502
|
describe('plural', function() {
|
@@ -3,33 +3,13 @@ describe('root wrapping', function () {
|
|
3
3
|
|
4
4
|
beforeEach(module('rails'));
|
5
5
|
|
6
|
-
var q, rootScope,
|
7
|
-
transformer, interceptor,
|
8
|
-
config = {config: {name: 'test', pluralName: 'tests'}};
|
6
|
+
var q, rootScope, railsRootWrapper, Resource;
|
9
7
|
|
10
|
-
|
11
|
-
function testTransform(wrappedData, unwrappedData) {
|
12
|
-
var result, resultPromise,
|
13
|
-
deferred = q.defer();
|
14
|
-
|
15
|
-
expect(transformer(unwrappedData, config)).toEqualData(wrappedData);
|
16
|
-
deferred.promise.resource = config;
|
17
|
-
expect(resultPromise = interceptor(deferred.promise)).toBeDefined();
|
18
|
-
|
19
|
-
resultPromise.then(function (response) {
|
20
|
-
result = response;
|
21
|
-
});
|
22
|
-
|
23
|
-
deferred.resolve({data: wrappedData});
|
24
|
-
rootScope.$digest(); // needed for $q to actually run callbacks
|
25
|
-
expect(result).toEqualData({data: unwrappedData});
|
26
|
-
}
|
27
|
-
|
28
|
-
beforeEach(inject(function ($rootScope, $q, railsRootWrappingTransformer, railsRootWrappingInterceptor) {
|
8
|
+
beforeEach(inject(function ($rootScope, $q, railsResourceFactory, _railsRootWrapper_) {
|
29
9
|
q = $q;
|
30
10
|
rootScope = $rootScope;
|
31
|
-
|
32
|
-
|
11
|
+
Resource = railsResourceFactory({name: 'test', pluralName: 'tests'});
|
12
|
+
railsRootWrapper = _railsRootWrapper_;
|
33
13
|
}));
|
34
14
|
|
35
15
|
it('should handle null root', function() {
|
@@ -43,4 +23,9 @@ describe('root wrapping', function () {
|
|
43
23
|
it('should transform object', function() {
|
44
24
|
testTransform({test: {abc: 'xyz', def: 'abc'}}, {abc: 'xyz', def: 'abc'});
|
45
25
|
});
|
26
|
+
|
27
|
+
function testTransform(wrappedData, unwrappedData) {
|
28
|
+
expect(railsRootWrapper.wrap(unwrappedData, Resource)).toEqualData(wrappedData);
|
29
|
+
expect(railsRootWrapper.unwrap({data: wrappedData}, Resource)).toEqualData({data: unwrappedData});
|
30
|
+
}
|
46
31
|
});
|
@@ -1,4 +1,4 @@
|
|
1
|
-
describe('transformers', function () {
|
1
|
+
describe('deprecated request transformers', function () {
|
2
2
|
'use strict';
|
3
3
|
var $httpBackend, $rootScope, factory, Test, testTransformer,
|
4
4
|
config = {
|
@@ -30,7 +30,6 @@ describe('transformers', function () {
|
|
30
30
|
$httpBackend.verifyNoOutstandingRequest();
|
31
31
|
});
|
32
32
|
|
33
|
-
|
34
33
|
it('should be able to add transformer using name', function() {
|
35
34
|
var Resource, testConfig = {};
|
36
35
|
|
@@ -8,9 +8,9 @@
|
|
8
8
|
};
|
9
9
|
|
10
10
|
RailsResourceSnapshotsMixin.extended = function (Resource) {
|
11
|
-
Resource.afterResponse
|
12
|
-
if (
|
13
|
-
|
11
|
+
Resource.intercept('afterResponse', function (result, resource, context) {
|
12
|
+
if (context && context.hasOwnProperty('$snapshots') && angular.isArray(context.$snapshots)) {
|
13
|
+
context.$snapshots.length = 0;
|
14
14
|
}
|
15
15
|
});
|
16
16
|
|
@@ -109,7 +109,10 @@
|
|
109
109
|
numVersions = snapshotsLength;
|
110
110
|
}
|
111
111
|
|
112
|
-
|
112
|
+
if (snapshotsLength) {
|
113
|
+
this.rollbackTo(this.$snapshots.length - numVersions);
|
114
|
+
}
|
115
|
+
|
113
116
|
return true;
|
114
117
|
}
|
115
118
|
|
@@ -1,21 +1,12 @@
|
|
1
1
|
(function (undefined) {
|
2
|
-
angular.module('rails').factory('
|
3
|
-
return
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
angular.module('rails').factory('railsRootWrappingInterceptor', function () {
|
11
|
-
return function (promise) {
|
12
|
-
var resource = promise.resource;
|
13
|
-
|
14
|
-
if (!resource) {
|
15
|
-
return promise;
|
16
|
-
}
|
17
|
-
|
18
|
-
return promise.then(function (response) {
|
2
|
+
angular.module('rails').factory('railsRootWrapper', function () {
|
3
|
+
return {
|
4
|
+
wrap: function (data, resource) {
|
5
|
+
var result = {};
|
6
|
+
result[angular.isArray(data) ? resource.config.pluralName : resource.config.name] = data;
|
7
|
+
return result;
|
8
|
+
},
|
9
|
+
unwrap: function (response, resource) {
|
19
10
|
if (response.data && response.data.hasOwnProperty(resource.config.name)) {
|
20
11
|
response.data = response.data[resource.config.name];
|
21
12
|
} else if (response.data && response.data.hasOwnProperty(resource.config.pluralName)) {
|
@@ -23,7 +14,7 @@
|
|
23
14
|
}
|
24
15
|
|
25
16
|
return response;
|
26
|
-
}
|
17
|
+
}
|
27
18
|
};
|
28
19
|
});
|
29
20
|
|
@@ -34,6 +25,7 @@
|
|
34
25
|
httpConfig: {},
|
35
26
|
defaultParams: undefined,
|
36
27
|
underscoreParams: true,
|
28
|
+
fullResponse: false,
|
37
29
|
extensions: []
|
38
30
|
};
|
39
31
|
|
@@ -91,6 +83,16 @@
|
|
91
83
|
return this;
|
92
84
|
};
|
93
85
|
|
86
|
+
/**
|
87
|
+
* Configures whether the full response from $http is returned or just the result data.
|
88
|
+
* @param {boolean} value true to return full $http response. Defaults to false.
|
89
|
+
* @returns {RailsResourceProvider} The provider instance
|
90
|
+
*/
|
91
|
+
this.fullResponse = function (value) {
|
92
|
+
defaultOptions.fullResponse = value;
|
93
|
+
return this;
|
94
|
+
};
|
95
|
+
|
94
96
|
/**
|
95
97
|
* List of RailsResource extensions to include by default.
|
96
98
|
*
|
@@ -105,28 +107,16 @@
|
|
105
107
|
return this;
|
106
108
|
};
|
107
109
|
|
108
|
-
this.$get = ['$http', '$q', 'railsUrlBuilder', 'railsSerializer', '
|
109
|
-
function ($http, $q, railsUrlBuilder, railsSerializer,
|
110
|
+
this.$get = ['$http', '$q', 'railsUrlBuilder', 'railsSerializer', 'railsRootWrapper', 'RailsResourceInjector',
|
111
|
+
function ($http, $q, railsUrlBuilder, railsSerializer, railsRootWrapper, RailsResourceInjector) {
|
110
112
|
|
111
113
|
function RailsResource(value) {
|
112
|
-
var instance = this;
|
113
|
-
this.$snapshots = [];
|
114
|
-
|
115
114
|
if (value) {
|
116
|
-
var
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
then: function (callback) {
|
122
|
-
this.response = callback(this.response, this.resource, this.context);
|
123
|
-
return immediatePromise(this.response);
|
124
|
-
}
|
125
|
-
};
|
126
|
-
};
|
127
|
-
|
128
|
-
var data = this.constructor.callInterceptors(immediatePromise({data: value}), this).response.data;
|
129
|
-
angular.extend(this, data);
|
115
|
+
var response = this.constructor.deserialize({data: value});
|
116
|
+
if (this.constructor.config.rootWrapping) {
|
117
|
+
response = railsRootWrapper.unwrap(response, this.constructor);
|
118
|
+
}
|
119
|
+
angular.extend(this, response.data);
|
130
120
|
}
|
131
121
|
}
|
132
122
|
|
@@ -226,10 +216,12 @@
|
|
226
216
|
this.config.defaultParams = cfg.defaultParams || defaultOptions.defaultParams;
|
227
217
|
this.config.underscoreParams = booleanParam(cfg.underscoreParams, defaultOptions.underscoreParams);
|
228
218
|
this.config.updateMethod = (cfg.updateMethod || defaultOptions.updateMethod).toLowerCase();
|
219
|
+
this.config.fullResponse = booleanParam(cfg.fullResponse, defaultOptions.fullResponse);
|
229
220
|
|
230
221
|
this.config.requestTransformers = cfg.requestTransformers ? cfg.requestTransformers.slice(0) : [];
|
231
222
|
this.config.responseInterceptors = cfg.responseInterceptors ? cfg.responseInterceptors.slice(0) : [];
|
232
223
|
this.config.afterResponseInterceptors = cfg.afterResponseInterceptors ? cfg.afterResponseInterceptors.slice(0) : [];
|
224
|
+
this.config.interceptors = cfg.interceptors ? cfg.interceptors.slice(0) : [];
|
233
225
|
|
234
226
|
this.config.serializer = RailsResourceInjector.getService(cfg.serializer || railsSerializer());
|
235
227
|
|
@@ -265,94 +257,241 @@
|
|
265
257
|
};
|
266
258
|
|
267
259
|
/**
|
268
|
-
*
|
260
|
+
* Interceptors utilize $q promises to allow for both synchronous and asynchronous processing during
|
261
|
+
* a request / response cycle.
|
262
|
+
*
|
263
|
+
* Interceptors can be added as a service factory name or as an object with properties matching one
|
264
|
+
* or more of the phases. Each property should have a value of a function to be called during that phase.
|
265
|
+
*
|
266
|
+
* There are multiple phases for both request and response. In addition, each phase has a corresponding
|
267
|
+
* error phase to handle promise rejections.
|
268
|
+
*
|
269
|
+
* Each request phase interceptor is called with the $http config object, the resource constructor, and if
|
270
|
+
* applicable the resource instance. The interceptor is free to modify the config or create a new one.
|
271
|
+
* The interceptor function must return a valid $http config or a promise that will eventually resolve
|
272
|
+
* to a config object.
|
273
|
+
*
|
274
|
+
* The valid request phases are:
|
275
|
+
*
|
276
|
+
* * beforeRequest: Interceptors are called prior to any data serialization or root wrapping.
|
277
|
+
* * beforeRequestError: Interceptors get called when a previous interceptor threw an error or
|
278
|
+
* resolved with a rejection.
|
279
|
+
* * beforeRequestWrapping: Interceptors are called after data serialization but before root wrapping.
|
280
|
+
* * beforeRequestWrappingError: Interceptors get called when a previous interceptor threw an error or
|
281
|
+
* resolved with a rejection.
|
282
|
+
* * request: Interceptors are called after any data serialization and root wrapping have been performed.
|
283
|
+
* * requestError: Interceptors get called when a previous interceptor threw an error or
|
284
|
+
* resolved with a rejection.
|
285
|
+
*
|
286
|
+
* The beforeResponse and response interceptors are called with the $http response object,
|
287
|
+
* the resource constructor, and if applicable the resource instance. The afterResponse interceptors
|
288
|
+
* are typically called with the response data instead of the full response object unless the config option
|
289
|
+
* fullResponse has been set to true. Like the request interceptor callbacks the response callbacks can
|
290
|
+
* manipulate the data or return new data. The interceptor function must return
|
291
|
+
*
|
292
|
+
* The valid response phases are:
|
293
|
+
*
|
294
|
+
* * beforeResponse: Interceptors are called prior to any data processing.
|
295
|
+
* * beforeResponseError: Interceptors get called when a previous interceptor threw an error or
|
296
|
+
* resolved with a rejection.
|
297
|
+
* * beforeResponseDeserialize: Interceptors are called after root unwrapping but prior to data deserializing.
|
298
|
+
* * beforeResponseDeserializeError: Interceptors get called when a previous interceptor threw an error or
|
299
|
+
* resolved with a rejection.
|
300
|
+
* * response: Interceptors are called after the data has been deserialized and root unwrapped but
|
301
|
+
* prior to the data being copied to the resource instance if applicable.
|
302
|
+
* * responseError: Interceptors get called when a previous interceptor threw an error or
|
303
|
+
* resolved with a rejection.
|
304
|
+
* * afterResponse: Interceptors are called at the very end of the response chain after all processing
|
305
|
+
* has been completed. The value of the first parameter is one of the following:
|
306
|
+
* - resource instance: When fullResponse is false and the operation was called on a resource instance.
|
307
|
+
* - response data: When fullResponse is false and the operation was called on the resource class.
|
308
|
+
* - $http response: When fullResponse is true
|
309
|
+
* * afterResponseError: Interceptors get called when a previous interceptor threw an error or
|
310
|
+
* resolved with a rejection.
|
311
|
+
*
|
312
|
+
* @param {String | Object} interceptor
|
313
|
+
*/
|
314
|
+
RailsResource.addInterceptor = function (interceptor) {
|
315
|
+
this.config.interceptors.push(interceptor);
|
316
|
+
};
|
317
|
+
|
318
|
+
/**
|
319
|
+
* Adds an interceptor callback function for the specified phase.
|
320
|
+
* @param {String} phase The interceptor phase, one of:
|
321
|
+
* beforeRequest, request, beforeResponse, response, afterResponse
|
322
|
+
* @param fn The function to call.
|
323
|
+
*/
|
324
|
+
RailsResource.intercept = function (phase, fn) {
|
325
|
+
var interceptor = {};
|
326
|
+
fn = RailsResourceInjector.getDependency(fn);
|
327
|
+
|
328
|
+
interceptor[phase] = function (value, resourceConstructor, context) {
|
329
|
+
return fn(value, resourceConstructor, context) || value;
|
330
|
+
};
|
331
|
+
|
332
|
+
this.addInterceptor(interceptor);
|
333
|
+
};
|
334
|
+
|
335
|
+
/**
|
336
|
+
* Adds interceptor on 'beforeRequest' phase.
|
337
|
+
* @param fn(httpConfig, constructor, context) - httpConfig is the config object to pass to $http,
|
338
|
+
* constructor is the resource class calling the function,
|
339
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
340
|
+
*/
|
341
|
+
RailsResource.interceptBeforeRequest = function (fn) {
|
342
|
+
this.intercept('beforeRequest', fn);
|
343
|
+
};
|
344
|
+
|
345
|
+
/**
|
346
|
+
* Adds interceptor on 'beforeRequestWrapping' phase.
|
347
|
+
* @param fn(httpConfig, constructor, context) - httpConfig is the config object to pass to $http,
|
348
|
+
* constructor is the resource class calling the function,
|
349
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
350
|
+
*/
|
351
|
+
RailsResource.interceptBeforeRequestWrapping = function (fn) {
|
352
|
+
this.intercept('beforeRequestWrapping', fn);
|
353
|
+
};
|
354
|
+
|
355
|
+
/**
|
356
|
+
* Adds interceptor on 'request' phase.
|
357
|
+
* @param fn(httpConfig, constructor, context) - httpConfig is the config object to pass to $http,
|
358
|
+
* constructor is the resource class calling the function,
|
359
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
360
|
+
*/
|
361
|
+
RailsResource.interceptRequest = function (fn) {
|
362
|
+
this.intercept('request', fn);
|
363
|
+
};
|
364
|
+
|
365
|
+
/**
|
366
|
+
* Adds interceptor on 'beforeResponse' phase.
|
367
|
+
* @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
|
368
|
+
* constructor is the resource class calling the function,
|
369
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
370
|
+
*/
|
371
|
+
RailsResource.interceptBeforeResponse = function (fn) {
|
372
|
+
this.intercept('beforeResponse', fn);
|
373
|
+
};
|
374
|
+
|
375
|
+
/**
|
376
|
+
* Adds interceptor on 'beforeResponseDeserialize' phase.
|
377
|
+
* @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
|
378
|
+
* constructor is the resource class calling the function,
|
379
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
380
|
+
*/
|
381
|
+
RailsResource.interceptBeforeResponseDeserialize = function (fn) {
|
382
|
+
this.intercept('beforeResponseDeserialize', fn);
|
383
|
+
};
|
384
|
+
|
385
|
+
/**
|
386
|
+
* Adds interceptor on 'response' phase.
|
387
|
+
* @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
|
388
|
+
* constructor is the resource class calling the function,
|
389
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
390
|
+
*/
|
391
|
+
RailsResource.interceptResponse = function (fn) {
|
392
|
+
this.intercept('response', fn);
|
393
|
+
};
|
394
|
+
|
395
|
+
/**
|
396
|
+
* Adds interceptor on 'afterResponse' phase.
|
397
|
+
* @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
|
398
|
+
* constructor is the resource class calling the function,
|
399
|
+
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
400
|
+
*/
|
401
|
+
RailsResource.interceptAfterResponse = function (fn) {
|
402
|
+
this.intercept('afterResponse', fn);
|
403
|
+
};
|
404
|
+
|
405
|
+
/**
|
406
|
+
* Deprecated, see interceptors
|
407
|
+
* Add a callback to run on response.
|
408
|
+
* @deprecated since version 1.0.0, use interceptResponse instead
|
269
409
|
* @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
|
270
410
|
* constructor is the resource class calling the function,
|
271
411
|
* context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
|
272
412
|
*/
|
273
413
|
RailsResource.beforeResponse = function (fn) {
|
274
414
|
fn = RailsResourceInjector.getDependency(fn);
|
275
|
-
this.
|
276
|
-
|
277
|
-
|
278
|
-
return response;
|
279
|
-
});
|
415
|
+
this.interceptResponse(function (response, resource, context) {
|
416
|
+
fn(response.data, resource.config.resourceConstructor, context);
|
417
|
+
return response;
|
280
418
|
});
|
281
419
|
};
|
282
420
|
|
283
421
|
/**
|
422
|
+
* Deprecated, see interceptors
|
284
423
|
* Add a callback to run after response has been processed. These callbacks are not called on object construction.
|
424
|
+
* @deprecated since version 1.0.0, use interceptAfterResponse instead
|
285
425
|
* @param fn(response data, constructor) - response data is either the resource instance returned or an array of resource instances and constructor is the resource class calling the function
|
286
426
|
*/
|
287
427
|
RailsResource.afterResponse = function (fn) {
|
288
428
|
fn = RailsResourceInjector.getDependency(fn);
|
289
|
-
this.
|
290
|
-
|
291
|
-
|
292
|
-
return response;
|
293
|
-
});
|
429
|
+
this.interceptAfterResponse(function (response, resource, context) {
|
430
|
+
fn(response, resource.config.resourceConstructor, context);
|
431
|
+
return response;
|
294
432
|
});
|
295
433
|
};
|
296
434
|
|
297
435
|
/**
|
436
|
+
* Deprecated, see interceptors
|
298
437
|
* Adds a function to run after serializing the data to send to the server, but before root-wrapping it.
|
438
|
+
* @deprecated since version 1.0.0, use interceptBeforeRequestWrapping instead
|
299
439
|
* @param fn (data, constructor) - data object is the serialized resource instance, and constructor the resource class calling the function
|
300
440
|
*/
|
301
441
|
RailsResource.beforeRequest = function (fn) {
|
302
442
|
fn = RailsResourceInjector.getDependency(fn);
|
303
|
-
this.
|
304
|
-
|
443
|
+
this.interceptBeforeRequestWrapping(function (httpConfig, resource) {
|
444
|
+
httpConfig.data = fn(httpConfig.data, resource.config.resourceConstructor) || httpConfig.data;
|
445
|
+
return httpConfig;
|
305
446
|
});
|
306
447
|
};
|
307
448
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
data = config.serializer.serialize(data);
|
312
|
-
|
313
|
-
forEachDependency(this.config.requestTransformers, function (transformer) {
|
314
|
-
data = transformer(data, config.resourceConstructor);
|
315
|
-
});
|
316
|
-
|
317
|
-
if (config.rootWrapping) {
|
318
|
-
data = railsRootWrappingTransformer(data, config.resourceConstructor);
|
449
|
+
RailsResource.serialize = function (httpConfig) {
|
450
|
+
if (httpConfig.data) {
|
451
|
+
httpConfig.data = this.config.serializer.serialize(httpConfig.data);
|
319
452
|
}
|
320
453
|
|
321
|
-
return
|
454
|
+
return httpConfig;
|
322
455
|
};
|
323
456
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
promise = railsRootWrappingInterceptor(promise);
|
337
|
-
}
|
338
|
-
|
339
|
-
promise.then(function (response) {
|
340
|
-
response.data = config.serializer.deserialize(response.data, config.resourceConstructor);
|
341
|
-
return response;
|
342
|
-
});
|
457
|
+
/**
|
458
|
+
* Deserializes the response data on the $http response. Stores the original version of the data
|
459
|
+
* on the response as "originalData" and sets the deserialized data in the "data" property.
|
460
|
+
* @param response The $http response object
|
461
|
+
* @returns {*} The $http response
|
462
|
+
*/
|
463
|
+
RailsResource.deserialize = function (response) {
|
464
|
+
// store off the data so we don't lose access to it after deserializing and unwrapping
|
465
|
+
response.originalData = response.data;
|
466
|
+
response.data = this.config.serializer.deserialize(response.data, this.config.resourceConstructor);
|
467
|
+
return response;
|
468
|
+
};
|
343
469
|
|
344
|
-
|
470
|
+
/**
|
471
|
+
* Deprecated, see interceptors
|
472
|
+
* Transform data after response has been converted to a resource instance
|
473
|
+
* @deprecated
|
474
|
+
* @param promise
|
475
|
+
* @param context
|
476
|
+
*/
|
477
|
+
RailsResource.callResponseInterceptors = function (promise, context) {
|
478
|
+
var config = this.config;
|
345
479
|
forEachDependency(config.responseInterceptors, function (interceptor) {
|
346
480
|
promise.resource = config.resourceConstructor;
|
347
481
|
promise.context = context;
|
348
482
|
promise = interceptor(promise);
|
349
483
|
});
|
350
|
-
|
351
484
|
return promise;
|
352
485
|
};
|
353
486
|
|
354
|
-
|
355
|
-
|
487
|
+
/**
|
488
|
+
* Deprecated, see interceptors
|
489
|
+
* Transform data after response has been converted to a resource instance
|
490
|
+
* @deprecated
|
491
|
+
* @param promise
|
492
|
+
* @param context
|
493
|
+
*/
|
494
|
+
RailsResource.callAfterResponseInterceptors = function (promise) {
|
356
495
|
var config = this.config;
|
357
496
|
// data is now deserialized. call response interceptors including afterResponse
|
358
497
|
forEachDependency(config.afterResponseInterceptors, function (interceptor) {
|
@@ -363,12 +502,100 @@
|
|
363
502
|
return promise;
|
364
503
|
};
|
365
504
|
|
366
|
-
RailsResource.
|
367
|
-
|
368
|
-
|
505
|
+
RailsResource.runInterceptorPhase = function (phase, context, promise) {
|
506
|
+
var config = this.config, chain = [];
|
507
|
+
|
508
|
+
forEachDependency(config.interceptors, function (interceptor) {
|
509
|
+
if (interceptor[phase] || interceptor[phase + 'Error']) {
|
510
|
+
chain.push(interceptor[phase], interceptor[phase + 'Error']);
|
511
|
+
}
|
512
|
+
});
|
513
|
+
|
514
|
+
while (chain.length) {
|
515
|
+
var thenFn = chain.shift();
|
516
|
+
var rejectFn = chain.shift();
|
517
|
+
|
518
|
+
promise = promise.then(createInterceptorSuccessCallback(thenFn, config.resourceConstructor, context),
|
519
|
+
createInterceptorRejectionCallback(rejectFn, config.resourceConstructor, context));
|
520
|
+
}
|
521
|
+
|
522
|
+
return promise;
|
523
|
+
};
|
524
|
+
|
525
|
+
/**
|
526
|
+
* Executes an HTTP request using $http.
|
527
|
+
*
|
528
|
+
* This method is used by all RailsResource operations that execute HTTP requests. Handles serializing
|
529
|
+
* the request data using the resource serializer, root wrapping (if enabled), deserializing the response
|
530
|
+
* data using the resource serializer, root unwrapping (if enabled), and copying the result back into the
|
531
|
+
* resource context if applicable. Executes interceptors at each phase of the request / response to allow
|
532
|
+
* users to build synchronous & asynchronous customizations to manipulate the data as necessary.
|
533
|
+
*
|
534
|
+
* @param httpConfig The config to pass to $http, see $http docs for details
|
535
|
+
* @param context An optional reference to the resource instance that is the context for the operation.
|
536
|
+
* If specified, the result data will be copied into the context during the response handling.
|
537
|
+
* @param resourceConfigOverrides An optional set of RailsResource configuration options overrides.
|
538
|
+
* These overrides allow users to build custom operations more easily with different resource settings.
|
539
|
+
* @returns {Promise} The promise that will eventually be resolved after all request / response handling
|
540
|
+
* has completed.
|
541
|
+
*/
|
542
|
+
RailsResource.$http = function (httpConfig, context, resourceConfigOverrides) {
|
543
|
+
var config = angular.extend(angular.copy(this.config), resourceConfigOverrides || {}),
|
544
|
+
resourceConstructor = config.resourceConstructor,
|
545
|
+
promise = $q.when(httpConfig);
|
546
|
+
|
547
|
+
promise = this.runInterceptorPhase('beforeRequest', context, promise).then(function (httpConfig) {
|
548
|
+
httpConfig = resourceConstructor.serialize(httpConfig);
|
549
|
+
|
550
|
+
forEachDependency(config.requestTransformers, function (transformer) {
|
551
|
+
httpConfig.data = transformer(httpConfig.data, config.resourceConstructor);
|
552
|
+
});
|
553
|
+
|
554
|
+
return httpConfig;
|
369
555
|
});
|
370
556
|
|
371
|
-
|
557
|
+
promise = this.runInterceptorPhase('beforeRequestWrapping', context, promise);
|
558
|
+
|
559
|
+
if (config.rootWrapping) {
|
560
|
+
promise = promise.then(function (httpConfig) {
|
561
|
+
httpConfig.data = railsRootWrapper.wrap(httpConfig.data, config.resourceConstructor);
|
562
|
+
return httpConfig;
|
563
|
+
});
|
564
|
+
}
|
565
|
+
|
566
|
+
promise = this.runInterceptorPhase('request', context, promise).then(function (httpConfig) {
|
567
|
+
return $http(httpConfig);
|
568
|
+
});
|
569
|
+
|
570
|
+
promise = this.runInterceptorPhase('beforeResponse', context, promise);
|
571
|
+
|
572
|
+
if (config.rootWrapping) {
|
573
|
+
promise = promise.then(function (response) {
|
574
|
+
return railsRootWrapper.unwrap(response, config.resourceConstructor);
|
575
|
+
});
|
576
|
+
}
|
577
|
+
|
578
|
+
promise = this.runInterceptorPhase('beforeResponseDeserialize', context, promise).then(function (response) {
|
579
|
+
return resourceConstructor.deserialize(response);
|
580
|
+
});
|
581
|
+
|
582
|
+
promise = this.callResponseInterceptors(promise, context);
|
583
|
+
promise = this.runInterceptorPhase('response', context, promise).then(function (response) {
|
584
|
+
if (context) {
|
585
|
+
// we may not have response data
|
586
|
+
if (response.hasOwnProperty('data') && angular.isObject(response.data)) {
|
587
|
+
angular.extend(context, response.data);
|
588
|
+
}
|
589
|
+
}
|
590
|
+
|
591
|
+
return config.fullResponse ? response : (context || response.data);
|
592
|
+
});
|
593
|
+
|
594
|
+
promise = this.callAfterResponseInterceptors(promise, context);
|
595
|
+
promise = this.runInterceptorPhase('afterResponse', context, promise);
|
596
|
+
promise.resource = config.resourceConstructor;
|
597
|
+
promise.context = context;
|
598
|
+
return promise;
|
372
599
|
};
|
373
600
|
|
374
601
|
/**
|
@@ -442,7 +669,7 @@
|
|
442
669
|
};
|
443
670
|
|
444
671
|
RailsResource.$get = function (url, queryParams) {
|
445
|
-
return this.
|
672
|
+
return this.$http(angular.extend({method: 'get', url: url}, this.getHttpConfig(queryParams)));
|
446
673
|
};
|
447
674
|
|
448
675
|
RailsResource.query = function (queryParams, context) {
|
@@ -463,36 +690,32 @@
|
|
463
690
|
return appendPath(this.constructor.resourceUrl(this), path);
|
464
691
|
};
|
465
692
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
return this.constructor
|
693
|
+
/**
|
694
|
+
* Executes $http with the resource instance as the context.
|
695
|
+
*
|
696
|
+
* @param httpConfig The config to pass to $http, see $http docs for details
|
697
|
+
* @param context An optional reference to the resource instance that is the context for the operation.
|
698
|
+
* If specified, the result data will be copied into the context during the response handling.
|
699
|
+
* @param resourceConfigOverrides An optional set of RailsResource configuration options overrides.
|
700
|
+
* These overrides allow users to build custom operations more easily with different resource settings.
|
701
|
+
* @returns {Promise} The promise that will eventually be resolved after all request / response handling
|
702
|
+
* has completed.
|
703
|
+
*/
|
704
|
+
RailsResource.prototype.$http = function (httpConfig, resourceConfigOverrides) {
|
705
|
+
return this.constructor.$http(httpConfig, this, resourceConfigOvverides);
|
479
706
|
};
|
480
707
|
|
481
708
|
angular.forEach(['post', 'put', 'patch'], function (method) {
|
482
709
|
RailsResource['$' + method] = function (url, data) {
|
483
|
-
var config;
|
484
710
|
// clone so we can manipulate w/o modifying the actual instance
|
485
|
-
data =
|
486
|
-
|
487
|
-
return this.processResponse($http(config));
|
711
|
+
data = angular.copy(data);
|
712
|
+
return this.$http(angular.extend({method: method, url: url, data: data}, this.getHttpConfig()));
|
488
713
|
};
|
489
714
|
|
490
715
|
RailsResource.prototype['$' + method] = function (url) {
|
491
|
-
var data, config;
|
492
716
|
// clone so we can manipulate w/o modifying the actual instance
|
493
|
-
data =
|
494
|
-
|
495
|
-
return this.processResponse($http(config));
|
717
|
+
var data = angular.copy(this, {});
|
718
|
+
return this.constructor.$http(angular.extend({method: method, url: url, data: data}, this.constructor.getHttpConfig()), this);
|
496
719
|
|
497
720
|
};
|
498
721
|
});
|
@@ -518,12 +741,12 @@
|
|
518
741
|
}
|
519
742
|
};
|
520
743
|
|
521
|
-
RailsResource.$delete = function (url) {
|
522
|
-
return this.
|
744
|
+
RailsResource.$delete = function (url, queryParams) {
|
745
|
+
return this.$http(angular.extend({method: 'delete', url: url}, this.getHttpConfig(queryParams)));
|
523
746
|
};
|
524
747
|
|
525
|
-
RailsResource.prototype.$delete = function (url) {
|
526
|
-
return this.
|
748
|
+
RailsResource.prototype.$delete = function (url, queryParams) {
|
749
|
+
return this.constructor.$http(angular.extend({method: 'delete', url: url}, this.constructor.getHttpConfig(queryParams)), this);
|
527
750
|
};
|
528
751
|
|
529
752
|
//using ['delete'] instead of .delete for IE7/8 compatibility
|
@@ -600,6 +823,19 @@
|
|
600
823
|
function booleanParam(value, defaultValue) {
|
601
824
|
return angular.isUndefined(value) ? defaultValue : value;
|
602
825
|
}
|
826
|
+
|
827
|
+
function createInterceptorSuccessCallback(thenFn, resourceConstructor, context) {
|
828
|
+
return function (data) {
|
829
|
+
return (thenFn || angular.identity)(data, resourceConstructor, context);
|
830
|
+
};
|
831
|
+
}
|
832
|
+
|
833
|
+
function createInterceptorRejectionCallback(rejectFn, resourceConstructor, context) {
|
834
|
+
return function (rejection) {
|
835
|
+
// can't use identity because we need to return a rejected promise to keep the error chain going
|
836
|
+
return rejectFn ? rejectFn(rejection, resourceConstructor, context) : $q.reject(rejection);
|
837
|
+
};
|
838
|
+
}
|
603
839
|
}];
|
604
840
|
});
|
605
841
|
|