angularjs-rails-resource 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -27,319 +27,350 @@
27
27
  };
28
28
  });
29
29
 
30
- angular.module('rails').factory('railsResourceFactory', ['$http', '$q', 'railsUrlBuilder', 'railsSerializer', 'railsRootWrappingTransformer', 'railsRootWrappingInterceptor', 'RailsResourceInjector',
30
+ angular.module('rails').provider('railsResourceFactory', function () {
31
+ var defaultOptions = {
32
+ enableRootWrapping: true,
33
+ updateMethod: 'put',
34
+ httpConfig: {},
35
+ defaultParams: undefined
36
+ };
37
+
38
+ this.enableRootWrapping = function (value) {
39
+ defaultOptions.enableRootWrapping = value;
40
+ return this;
41
+ };
42
+
43
+ this.updateMethod = function (value) {
44
+ defaultOptions.updateMethod = value;
45
+ return this;
46
+ };
47
+
48
+ this.httpConfig = function (value) {
49
+ defaultOptions.httpConfig = value;
50
+ return this;
51
+ };
52
+
53
+ this.defaultParams = function (value) {
54
+ defaultOptions.defaultParams = value;
55
+ return this;
56
+ };
57
+
58
+ this.$get = ['$http', '$q', 'railsUrlBuilder', 'railsSerializer', 'railsRootWrappingTransformer', 'railsRootWrappingInterceptor', 'RailsResourceInjector',
31
59
  function ($http, $q, railsUrlBuilder, railsSerializer, railsRootWrappingTransformer, railsRootWrappingInterceptor, RailsResourceInjector) {
32
60
 
33
- function railsResourceFactory(config) {
34
- var transformers = config.requestTransformers,
35
- interceptors = config.responseInterceptors,
36
- afterInterceptors = config.afterResponseInterceptors;
61
+ function railsResourceFactory(config) {
62
+ var transformers = config.requestTransformers,
63
+ interceptors = config.responseInterceptors,
64
+ afterInterceptors = config.afterResponseInterceptors;
37
65
 
38
- function appendPath(url, path) {
39
- if (path) {
40
- if (path[0] !== '/') {
41
- url += '/';
66
+ function appendPath(url, path) {
67
+ if (path) {
68
+ if (path[0] !== '/') {
69
+ url += '/';
70
+ }
71
+
72
+ url += path;
42
73
  }
43
74
 
44
- url += path;
75
+ return url;
45
76
  }
46
77
 
47
- return url;
48
- }
78
+ function RailsResource(value) {
79
+ var instance = this;
80
+ if (value) {
81
+ var immediatePromise = function(data) {
82
+ return {
83
+ resource: RailsResource,
84
+ context: instance,
85
+ response: data,
86
+ then: function(callback) {
87
+ this.response = callback(this.response, this.resource, this.context);
88
+ return immediatePromise(this.response);
89
+ }
90
+ }
91
+ };
92
+
93
+ var data = RailsResource.callInterceptors(immediatePromise({data: value}), this).response.data;
94
+ angular.extend(this, data);
95
+ }
96
+ }
49
97
 
50
- function RailsResource(value) {
51
- var instance = this;
52
- if (value) {
53
- var immediatePromise = function(data) {
54
- return {
55
- resource: RailsResource,
56
- context: instance,
57
- response: data,
58
- then: function(callback) {
59
- this.response = callback(this.response, this.resource, this.context);
60
- return immediatePromise(this.response);
61
- }
62
- }
63
- };
98
+ RailsResource.setUrl = function(url) {
99
+ RailsResource.url = railsUrlBuilder(url);
100
+ };
101
+ RailsResource.setUrl(config.url);
102
+
103
+ RailsResource.enableRootWrapping = config.wrapData === undefined ? defaultOptions.enableRootWrapping : config.wrapData; // using undefined check because config.wrapData || true would be true when config.wrapData === false
104
+ RailsResource.httpConfig = config.httpConfig || defaultOptions.httpConfig;
105
+ RailsResource.httpConfig.headers = angular.extend({'Accept': 'application/json', 'Content-Type': 'application/json'}, RailsResource.httpConfig.headers || {});
106
+ RailsResource.defaultParams = config.defaultParams || defaultOptions.defaultParams;
107
+ RailsResource.updateMethod = (config.updateMethod || defaultOptions.updateMethod).toLowerCase();
108
+
109
+ RailsResource.requestTransformers = [];
110
+ RailsResource.responseInterceptors = [];
111
+ RailsResource.afterResponseInterceptors = [];
112
+ RailsResource.serializer = RailsResourceInjector.createService(config.serializer || railsSerializer());
113
+ RailsResource.rootName = RailsResource.serializer.underscore(config.name);
114
+ RailsResource.rootPluralName = RailsResource.serializer.underscore(config.pluralName || RailsResource.serializer.pluralize(config.name));
115
+
116
+ /**
117
+ * Add a callback to run on response and construction.
118
+ * @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
119
+ * constructor is the resource class calling the function,
120
+ * context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
121
+ */
122
+ RailsResource.beforeResponse = function(fn) {
123
+ fn = RailsResourceInjector.getDependency(fn);
124
+ RailsResource.responseInterceptors.push(function(promise) {
125
+ return promise.then(function(response) {
126
+ fn(response.data, promise.resource, promise.context);
127
+ return response;
128
+ });
129
+ });
130
+ };
64
131
 
65
- var data = RailsResource.callInterceptors(immediatePromise({data: value}), this).response.data;
66
- angular.extend(this, data);
67
- }
68
- }
132
+ /**
133
+ * Add a callback to run after response has been processed. These callbacks are not called on object construction.
134
+ * @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
135
+ */
136
+ RailsResource.afterResponse = function(fn) {
137
+ fn = RailsResourceInjector.getDependency(fn);
138
+ RailsResource.afterResponseInterceptors.push(function(promise) {
139
+ return promise.then(function(response) {
140
+ fn(response, promise.resource);
141
+ return response;
142
+ });
143
+ });
144
+ };
145
+
146
+ /**
147
+ * Adds a function to run after serializing the data to send to the server, but before root-wrapping it.
148
+ * @param fn (data, constructor) - data object is the serialized resource instance, and constructor the resource class calling the function
149
+ */
150
+ RailsResource.beforeRequest = function(fn) {
151
+ fn = RailsResourceInjector.getDependency(fn);
152
+ RailsResource.requestTransformers.push(function(data, resource) {
153
+ return fn(data, resource) || data;
154
+ });
155
+ };
69
156
 
70
- RailsResource.setUrl = function(url) {
71
- RailsResource.url = railsUrlBuilder(url);
72
- };
73
- RailsResource.setUrl(config.url);
74
-
75
- RailsResource.enableRootWrapping = config.wrapData === undefined ? true : config.wrapData;
76
- RailsResource.httpConfig = config.httpConfig || {};
77
- RailsResource.httpConfig.headers = angular.extend({'Accept': 'application/json', 'Content-Type': 'application/json'}, RailsResource.httpConfig.headers || {});
78
- RailsResource.requestTransformers = [];
79
- RailsResource.responseInterceptors = [];
80
- RailsResource.afterResponseInterceptors = [];
81
- RailsResource.defaultParams = config.defaultParams;
82
- RailsResource.serializer = RailsResourceInjector.createService(config.serializer || railsSerializer());
83
- RailsResource.rootName = RailsResource.serializer.underscore(config.name);
84
- RailsResource.rootPluralName = RailsResource.serializer.underscore(config.pluralName || RailsResource.serializer.pluralize(config.name));
85
-
86
- /**
87
- * Add a callback to run on response and construction.
88
- * @param fn(response data, constructor, context) - response data is either the resource instance returned or an array of resource instances,
89
- * constructor is the resource class calling the function,
90
- * context is the resource instance of the calling method (create, update, delete) or undefined if the method was a class method (get, query)
91
- */
92
- RailsResource.beforeResponse = function(fn) {
93
- fn = RailsResourceInjector.getDependency(fn);
94
- RailsResource.responseInterceptors.push(function(promise) {
95
- return promise.then(function(response) {
96
- fn(response.data, promise.resource, promise.context);
97
- return response;
157
+ // copied from $HttpProvider to support interceptors being dependency names or anonymous factory functions
158
+ angular.forEach(interceptors, function (interceptor) {
159
+ RailsResource.responseInterceptors.push(RailsResourceInjector.getDependency(interceptor));
98
160
  });
99
- });
100
- };
101
-
102
- /**
103
- * Add a callback to run after response has been processed. These callbacks are not called on object construction.
104
- * @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
105
- */
106
- RailsResource.afterResponse = function(fn) {
107
- fn = RailsResourceInjector.getDependency(fn);
108
- RailsResource.afterResponseInterceptors.push(function(promise) {
109
- return promise.then(function(response) {
110
- fn(response, promise.resource);
111
- return response;
161
+
162
+ angular.forEach(afterInterceptors, function (interceptor) {
163
+ RailsResource.afterResponseInterceptors.push(RailsResourceInjector.getDependency(interceptor));
112
164
  });
113
- });
114
- };
115
-
116
- /**
117
- * Adds a function to run after serializing the data to send to the server, but before root-wrapping it.
118
- * @param fn (data, constructor) - data object is the serialized resource instance, and constructor the resource class calling the function
119
- */
120
- RailsResource.beforeRequest = function(fn) {
121
- fn = RailsResourceInjector.getDependency(fn);
122
- RailsResource.requestTransformers.push(function(data, resource) {
123
- return fn(data, resource) || data;
124
- });
125
- };
126
-
127
- // copied from $HttpProvider to support interceptors being dependency names or anonymous factory functions
128
- angular.forEach(interceptors, function (interceptor) {
129
- RailsResource.responseInterceptors.push(RailsResourceInjector.getDependency(interceptor));
130
- });
131
165
 
132
- angular.forEach(afterInterceptors, function (interceptor) {
133
- RailsResource.afterResponseInterceptors.push(RailsResourceInjector.getDependency(interceptor));
134
- });
166
+ angular.forEach(transformers, function (transformer) {
167
+ RailsResource.requestTransformers.push(RailsResourceInjector.getDependency(transformer));
168
+ });
135
169
 
136
- angular.forEach(transformers, function (transformer) {
137
- RailsResource.requestTransformers.push(RailsResourceInjector.getDependency(transformer));
138
- });
170
+ // transform data for request:
171
+ RailsResource.transformData = function (data) {
172
+ data = RailsResource.serializer.serialize(data);
139
173
 
140
- // transform data for request:
141
- RailsResource.transformData = function (data) {
142
- data = RailsResource.serializer.serialize(data);
174
+ // data is now serialized. call request transformers including beforeRequest
175
+ angular.forEach(RailsResource.requestTransformers, function (transformer) {
176
+ data = transformer(data, RailsResource);
177
+ });
143
178
 
144
- // data is now serialized. call request transformers including beforeRequest
145
- angular.forEach(RailsResource.requestTransformers, function (transformer) {
146
- data = transformer(data, RailsResource);
147
- });
148
179
 
180
+ if (RailsResource.enableRootWrapping) {
181
+ data = railsRootWrappingTransformer(data, RailsResource);
182
+ }
149
183
 
150
- if (RailsResource.enableRootWrapping) {
151
- data = railsRootWrappingTransformer(data, RailsResource);
152
- }
184
+ return data;
185
+ };
153
186
 
154
- return data;
155
- };
187
+ // transform data on response:
188
+ RailsResource.callInterceptors = function (promise, context) {
189
+ promise = promise.then(function (response) {
190
+ // store off the data in case something (like our root unwrapping) assigns data as a new object
191
+ response.originalData = response.data;
192
+ return response;
193
+ });
194
+
195
+ if (RailsResource.enableRootWrapping) {
196
+ promise.resource = RailsResource;
197
+ promise = railsRootWrappingInterceptor(promise);
198
+ }
156
199
 
157
- // transform data on response:
158
- RailsResource.callInterceptors = function (promise, context) {
159
- promise = promise.then(function (response) {
160
- // store off the data in case something (like our root unwrapping) assigns data as a new object
161
- response.originalData = response.data;
162
- return response;
163
- });
200
+ promise.then(function (response) {
201
+ response.data = RailsResource.serializer.deserialize(response.data, RailsResource);
202
+ return response;
203
+ });
164
204
 
165
- if (RailsResource.enableRootWrapping) {
166
- promise.resource = RailsResource;
167
- promise = railsRootWrappingInterceptor(promise);
168
- }
205
+ // data is now deserialized. call response interceptors including beforeResponse
206
+ angular.forEach(RailsResource.responseInterceptors, function (interceptor) {
207
+ promise.resource = RailsResource;
208
+ promise.context = context;
209
+ promise = interceptor(promise);
210
+ });
169
211
 
170
- promise.then(function (response) {
171
- response.data = RailsResource.serializer.deserialize(response.data, RailsResource);
172
- return response;
173
- });
212
+ return promise;
213
+ };
174
214
 
175
- // data is now deserialized. call response interceptors including beforeResponse
176
- angular.forEach(RailsResource.responseInterceptors, function (interceptor) {
177
- promise.resource = RailsResource;
178
- promise.context = context;
179
- promise = interceptor(promise);
180
- });
215
+ // transform data after response has been converted to a resource instance:
216
+ RailsResource.callAfterInterceptors = function (promise) {
217
+ // data is now deserialized. call response interceptors including afterResponse
218
+ angular.forEach(RailsResource.afterResponseInterceptors, function (interceptor) {
219
+ promise.resource = RailsResource;
220
+ promise = interceptor(promise);
221
+ });
181
222
 
182
- return promise;
183
- };
184
-
185
- // transform data after response has been converted to a resource instance:
186
- RailsResource.callAfterInterceptors = function (promise) {
187
- // data is now deserialized. call response interceptors including afterResponse
188
- angular.forEach(RailsResource.afterResponseInterceptors, function (interceptor) {
189
- promise.resource = RailsResource;
190
- promise = interceptor(promise);
191
- });
223
+ return promise;
224
+ };
192
225
 
193
- return promise;
194
- };
226
+ RailsResource.processResponse = function (promise) {
227
+ promise = RailsResource.callInterceptors(promise).then(function (response) {
228
+ return response.data;
229
+ });
195
230
 
196
- RailsResource.processResponse = function (promise) {
197
- promise = RailsResource.callInterceptors(promise).then(function (response) {
198
- return response.data;
199
- });
200
-
201
- return RailsResource.callAfterInterceptors(promise);
202
- };
231
+ return RailsResource.callAfterInterceptors(promise);
232
+ };
203
233
 
204
- RailsResource.getParameters = function (queryParams) {
205
- var params;
234
+ RailsResource.getParameters = function (queryParams) {
235
+ var params;
206
236
 
207
- if (RailsResource.defaultParams) {
208
- params = RailsResource.defaultParams;
209
- }
237
+ if (RailsResource.defaultParams) {
238
+ params = RailsResource.defaultParams;
239
+ }
210
240
 
211
- if (angular.isObject(queryParams)) {
212
- params = angular.extend(params || {}, queryParams);
213
- }
241
+ if (angular.isObject(queryParams)) {
242
+ params = angular.extend(params || {}, queryParams);
243
+ }
214
244
 
215
- return params;
216
- };
245
+ return params;
246
+ };
217
247
 
218
- RailsResource.getHttpConfig = function (queryParams) {
219
- var params = RailsResource.getParameters(queryParams);
248
+ RailsResource.getHttpConfig = function (queryParams) {
249
+ var params = RailsResource.getParameters(queryParams);
220
250
 
221
- if (params) {
222
- return angular.extend({params: params}, RailsResource.httpConfig);
223
- }
251
+ if (params) {
252
+ return angular.extend({params: params}, RailsResource.httpConfig);
253
+ }
224
254
 
225
- return angular.copy(RailsResource.httpConfig);
226
- };
227
-
228
- /**
229
- * Returns a URL from the given parameters. You can override this method on your resource definitions to provide
230
- * custom logic for building your URLs or you can utilize the parameterized url strings to substitute values in the
231
- * URL string.
232
- *
233
- * The parameters in the URL string follow the normal Angular binding expression using {{ and }} for the start/end symbols.
234
- *
235
- * If the context is a number and the URL string does not contain an id parameter then the number is appended
236
- * to the URL string.
237
- *
238
- * If the context is a number and the URL string does
239
- * @param context
240
- * @param path {string} (optional) An additional path to append to the URL
241
- * @return {string}
242
- */
243
- RailsResource.$url = RailsResource.resourceUrl = function (context, path) {
244
- if (!angular.isObject(context)) {
245
- context = {id: context};
246
- }
255
+ return angular.copy(RailsResource.httpConfig);
256
+ };
247
257
 
248
- return appendPath(RailsResource.url(context || {}), path);
249
- };
250
-
251
- RailsResource.$get = function (url, queryParams) {
252
- return RailsResource.processResponse($http.get(url, RailsResource.getHttpConfig(queryParams)));
253
- };
254
-
255
- RailsResource.query = function (queryParams, context) {
256
- return RailsResource.$get(RailsResource.resourceUrl(context), queryParams);
257
- };
258
-
259
- RailsResource.get = function (context, queryParams) {
260
- return RailsResource.$get(RailsResource.resourceUrl(context), queryParams);
261
- };
262
-
263
- /**
264
- * Returns the URL for this resource.
265
- *
266
- * @param path {string} (optional) An additional path to append to the URL
267
- * @returns {string} The URL for the resource
268
- */
269
- RailsResource.prototype.$url = function(path) {
270
- return appendPath(RailsResource.resourceUrl(this), path);
271
- };
272
-
273
- RailsResource.prototype.processResponse = function (promise) {
274
- promise = RailsResource.callInterceptors(promise, this);
275
-
276
- promise = promise.then(angular.bind(this, function (response) {
277
- // we may not have response data
278
- if (response.hasOwnProperty('data') && angular.isObject(response.data)) {
279
- angular.extend(this, response.data);
258
+ /**
259
+ * Returns a URL from the given parameters. You can override this method on your resource definitions to provide
260
+ * custom logic for building your URLs or you can utilize the parameterized url strings to substitute values in the
261
+ * URL string.
262
+ *
263
+ * The parameters in the URL string follow the normal Angular binding expression using {{ and }} for the start/end symbols.
264
+ *
265
+ * If the context is a number and the URL string does not contain an id parameter then the number is appended
266
+ * to the URL string.
267
+ *
268
+ * If the context is a number and the URL string does
269
+ * @param context
270
+ * @param path {string} (optional) An additional path to append to the URL
271
+ * @return {string}
272
+ */
273
+ RailsResource.$url = RailsResource.resourceUrl = function (context, path) {
274
+ if (!angular.isObject(context)) {
275
+ context = {id: context};
280
276
  }
281
277
 
282
- return this;
283
- }));
278
+ return appendPath(RailsResource.url(context || {}), path);
279
+ };
284
280
 
285
- return RailsResource.callAfterInterceptors(promise);
286
- };
281
+ RailsResource.$get = function (url, queryParams) {
282
+ return RailsResource.processResponse($http.get(url, RailsResource.getHttpConfig(queryParams)));
283
+ };
287
284
 
288
- angular.forEach(['post', 'put', 'patch'], function (method) {
289
- RailsResource['$' + method] = function (url, data) {
290
- var config;
291
- // clone so we can manipulate w/o modifying the actual instance
292
- data = RailsResource.transformData(angular.copy(data, {}));
293
- config = angular.extend({method: method, url: url, data: data}, RailsResource.getHttpConfig());
294
- return RailsResource.processResponse($http(config));
285
+ RailsResource.query = function (queryParams, context) {
286
+ return RailsResource.$get(RailsResource.resourceUrl(context), queryParams);
295
287
  };
296
288
 
297
- RailsResource.prototype['$' + method] = function (url) {
298
- var data, config;
299
- // clone so we can manipulate w/o modifying the actual instance
300
- data = RailsResource.transformData(angular.copy(this, {}));
301
- config = angular.extend({method: method, url: url, data: data}, RailsResource.getHttpConfig());
302
- return this.processResponse($http(config));
289
+ RailsResource.get = function (context, queryParams) {
290
+ return RailsResource.$get(RailsResource.resourceUrl(context), queryParams);
291
+ };
303
292
 
293
+ /**
294
+ * Returns the URL for this resource.
295
+ *
296
+ * @param path {string} (optional) An additional path to append to the URL
297
+ * @returns {string} The URL for the resource
298
+ */
299
+ RailsResource.prototype.$url = function(path) {
300
+ return appendPath(RailsResource.resourceUrl(this), path);
304
301
  };
305
- });
306
302
 
307
- RailsResource.prototype.create = function () {
308
- return this.$post(this.$url(), this);
309
- };
303
+ RailsResource.prototype.processResponse = function (promise) {
304
+ promise = RailsResource.callInterceptors(promise, this);
310
305
 
311
- RailsResource.prototype.update = function () {
312
- return this.$put(this.$url(), this);
313
- };
306
+ promise = promise.then(angular.bind(this, function (response) {
307
+ // we may not have response data
308
+ if (response.hasOwnProperty('data') && angular.isObject(response.data)) {
309
+ angular.extend(this, response.data);
310
+ }
314
311
 
315
- RailsResource.prototype.isNew = function () {
316
- return this.id == null;
317
- }
312
+ return this;
313
+ }));
318
314
 
319
- RailsResource.prototype.save = function () {
320
- if (this.isNew()) {
321
- return this.create();
322
- } else {
323
- return this.update();
315
+ return RailsResource.callAfterInterceptors(promise);
316
+ };
317
+
318
+ angular.forEach(['post', 'put', 'patch'], function (method) {
319
+ RailsResource['$' + method] = function (url, data) {
320
+ var config;
321
+ // clone so we can manipulate w/o modifying the actual instance
322
+ data = RailsResource.transformData(angular.copy(data, {}));
323
+ config = angular.extend({method: method, url: url, data: data}, RailsResource.getHttpConfig());
324
+ return RailsResource.processResponse($http(config));
325
+ };
326
+
327
+ RailsResource.prototype['$' + method] = function (url) {
328
+ var data, config;
329
+ // clone so we can manipulate w/o modifying the actual instance
330
+ data = RailsResource.transformData(angular.copy(this, {}));
331
+ config = angular.extend({method: method, url: url, data: data}, RailsResource.getHttpConfig());
332
+ return this.processResponse($http(config));
333
+
334
+ };
335
+ });
336
+
337
+ RailsResource.prototype.create = function () {
338
+ return this.$post(this.$url(), this);
339
+ };
340
+
341
+ RailsResource.prototype.update = function () {
342
+ return this['$' + RailsResource.updateMethod](this.$url(), this);
343
+ };
344
+
345
+ RailsResource.prototype.isNew = function () {
346
+ return this.id == null;
347
+ }
348
+
349
+ RailsResource.prototype.save = function () {
350
+ if (this.isNew()) {
351
+ return this.create();
352
+ } else {
353
+ return this.update();
354
+ }
324
355
  }
325
- }
326
356
 
327
- RailsResource['$delete'] = function (url) {
328
- return RailsResource.processResponse($http['delete'](url, RailsResource.getHttpConfig()));
329
- };
357
+ RailsResource['$delete'] = function (url) {
358
+ return RailsResource.processResponse($http['delete'](url, RailsResource.getHttpConfig()));
359
+ };
330
360
 
331
- RailsResource.prototype['$delete'] = function (url) {
332
- return this.processResponse($http['delete'](url, RailsResource.getHttpConfig()));
333
- };
361
+ RailsResource.prototype['$delete'] = function (url) {
362
+ return this.processResponse($http['delete'](url, RailsResource.getHttpConfig()));
363
+ };
334
364
 
335
- //using ['delete'] instead of .delete for IE7/8 compatibility
336
- RailsResource.prototype.remove = RailsResource.prototype['delete'] = function () {
337
- return this.$delete(this.$url());
338
- };
365
+ //using ['delete'] instead of .delete for IE7/8 compatibility
366
+ RailsResource.prototype.remove = RailsResource.prototype['delete'] = function () {
367
+ return this.$delete(this.$url());
368
+ };
339
369
 
340
- return RailsResource;
341
- }
370
+ return RailsResource;
371
+ }
342
372
 
343
- return railsResourceFactory;
344
- }]);
373
+ return railsResourceFactory;
374
+ }];
375
+ });
345
376
  }());