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.
- checksums.yaml +8 -8
- data/README.md +39 -4
- data/angularjs-rails-resource.gemspec +2 -1
- data/lib/angularjs-rails-resource/version.rb +1 -1
- data/test/unit/angularjs/rails/resourceProviderSpec.js +43 -0
- data/test/unit/angularjs/rails/resourceSpec.js +47 -0
- data/test/unit/angularjs/rails/serializationSpec.js +345 -283
- data/vendor/assets/javascripts/angularjs/rails/resource/resource.js +294 -263
- data/vendor/assets/javascripts/angularjs/rails/resource/serialization.js +486 -431
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZGU4OWY0N2I0MGNjN2U0OGQ1OGZmZWE2ODgwYTlhZWIwZGMxOTdjZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NmNkNDkxOWRhMzJkNGU0MTVhODFmN2FlZmI1ZmM4NzgxM2NhYmM3Zg==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
OGJiNjBiOGYzMjczNTcyZmE2NGZjZDQ5NjJjYjI0Nzk3MTA5YmNiOTk5OGU0
|
10
|
+
YmNjYTMzY2RjNzExNzA2YjlmMmYwNGQ3YzgyZmVhYjBkMGEwZGJiOTIwOGE0
|
11
|
+
NmY1MzY0MGMyOWZkYTIwNDQyY2RiNmY3NmY1YjBlYzZmNTkzN2Y=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
Yzg0YjlhMjJlZDc3ZTdjMmY0NWQxZWUyZTBhMGFmODM5M2Q0ZmRjY2VhNjlk
|
14
|
+
ZWEwNWNlN2M3ZWQzOTg4NTQwN2EzZmEzMzc1YWUxY2I1ZGQ4YTQxYjg2ZjE1
|
15
|
+
MTMzNDk3MmRhNmRjZTg2MTllNjhhYTg5YjAyMDM4MGFlMjlmOTE=
|
data/README.md
CHANGED
@@ -132,6 +132,7 @@ The following options are available for the config object passed to the factory
|
|
132
132
|
* **Accept** - application/json
|
133
133
|
* **Content-Type** - application/json
|
134
134
|
* **defaultParams** *(optional)* - If the resource expects a default set of query params on every call you can specify them here.
|
135
|
+
* **updateMethod** *(optional)* - Allows overriding the default HTTP method (PUT) used for update. Valid values are "post", "put", or "patch".
|
135
136
|
* **requestTransformers** *(optional) - See [Transformers / Interceptors](#transformers--interceptors)
|
136
137
|
* **responseInterceptors** *(optional)* - See [Transformers / Interceptors](#transformers--interceptors)
|
137
138
|
* **afterResponseInterceptors** *(optional)* - See [Transformers / Interceptors](#transformers--interceptors)
|
@@ -139,6 +140,24 @@ The following options are available for the config object passed to the factory
|
|
139
140
|
**NOTE:** The names should be specified using camel case when using the key transformations because that happens before the root wrapping by default.
|
140
141
|
For example, you should specify "publishingCompany" and "publishingCompanies" instead of "publishing_company" and "publishing_companies".
|
141
142
|
|
143
|
+
### Provider Configuration
|
144
|
+
<code>railsResourceFactory</code> can be injected as <code>railsResourceFactoryProvider</code> into your app's config method to configure defaults for all the resources application-wide.
|
145
|
+
The individual resource configuration takes precedence over application-wide default configuration values.
|
146
|
+
Each configuration option listed is exposed as a method on the provider that takes the configuration value as the parameter and returns the provider to allow method chaining.
|
147
|
+
|
148
|
+
* enableRootWrapping - {function(boolean):railsSerializerProvider}
|
149
|
+
* httpConfig - {function(object):railsSerializerProvider}
|
150
|
+
* defaultParams - {function(object):railsSerializerProvider}
|
151
|
+
* updateMethod - {function(boolean):railsSerializerProvider}
|
152
|
+
|
153
|
+
For example, to turn off the root wrapping application-wide and set the update method to PATCH:
|
154
|
+
|
155
|
+
````javascript
|
156
|
+
app.config(function (railsResourceFactoryProvider) {
|
157
|
+
railsResourceFactoryProvider.enableRootWrapping(false).updateMethod('patch');
|
158
|
+
);
|
159
|
+
````
|
160
|
+
|
142
161
|
## Resource URLs
|
143
162
|
The URL can be specified as one of three ways:
|
144
163
|
|
@@ -259,8 +278,8 @@ AngularJS automatically excludes all attribute keys that begin with $ in their t
|
|
259
278
|
* **returns** {Serializer} - A Serializer constructor function
|
260
279
|
|
261
280
|
### Configuration
|
262
|
-
The <code>railsSerializer</code> function takes a customizer function that is called on create within the context of the constructed Serializer.
|
263
|
-
|
281
|
+
The <code>railsSerializer</code> function takes a customizer function that is called on create within the context of the constructed Serializer.
|
282
|
+
From within the customizer function you can call customization functions that affect what gets serialized and how or override the default options.
|
264
283
|
|
265
284
|
#### Configuration Options
|
266
285
|
Serializers have the following available configuration options:
|
@@ -279,13 +298,29 @@ Serializers have the following available configuration options:
|
|
279
298
|
* parameters
|
280
299
|
* **attribute** {string} - The name as it appeared in the JSON
|
281
300
|
* **returns** {string} - The name as it should appear in the resource
|
282
|
-
* excludeByDefault {boolean} - Specifies whether or not JSON serialization should exclude all attributes from serialization by default.
|
283
|
-
* default: false
|
284
301
|
* exclusionMatchers {array} - An list of rules that should be applied to determine whether or not an attribute should be excluded. The values in the array can be one of the following types:
|
285
302
|
* string - Defines a prefix that is used to test for exclusion
|
286
303
|
* RegExp - A custom regular expression that is tested against the attribute name
|
287
304
|
* function - A custom function that accepts a string argument and returns a boolean with true indicating exclusion.
|
288
305
|
|
306
|
+
#### Provider Configuration
|
307
|
+
<code>railsSerializer</code> can be injected as <code>railsSerializerProvider</code> into your app's config method to configure defaults for all the serializers application-wide.
|
308
|
+
Each configuration option listed is exposed as a method on the provider that takes the configuration value as the parameter and returns the provider to allow method chaining.
|
309
|
+
|
310
|
+
* underscore - {function(fn):railsSerializerProvider}
|
311
|
+
* camelize - {function(fn):railsSerializerProvider}
|
312
|
+
* pluralize - {function(fn):railsSerializerProvider}
|
313
|
+
* exclusionMatchers - {function(matchers):railsSerializerProvider}
|
314
|
+
|
315
|
+
For example, to turn off the key renaming from underscore to camel case and vice versa you would do:
|
316
|
+
|
317
|
+
````javascript
|
318
|
+
app.config(function (railsSerializerProvider) {
|
319
|
+
railsSerializerProvider.underscore(function (value) { return value; })
|
320
|
+
.camelize(function (value) { return value; });
|
321
|
+
);
|
322
|
+
````
|
323
|
+
|
289
324
|
#### Customization API
|
290
325
|
The customizer function passed to the railsSerializer has available to it the following methods for altering the serialization of an object. None of these methods support nested attribute names (e.g. <code>'books.publicationDate'</code>), in order to customize the serialization of the <code>books</code> objects you would need to specify a custom serializer for the <code>books</code> attribute.
|
291
326
|
|
@@ -5,8 +5,9 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.authors = ["Tommy Odom", "Chris Chase"]
|
6
6
|
gem.email = ["odom@finelineprototyping.com", "chris@finelineprototyping.com"]
|
7
7
|
gem.description = %q{A small AngularJS add-on for integrating with Rails via JSON more easily.}
|
8
|
-
gem.summary = %q{}
|
8
|
+
gem.summary = %q{AngularJS add-on resource add-on for integrating with Rails}
|
9
9
|
gem.homepage = "https://github.com/finelineprototyping/angularjs-rails-resource"
|
10
|
+
gem.license = 'MIT'
|
10
11
|
|
11
12
|
gem.files = `git ls-files`.split($\)
|
12
13
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
describe('resource provider factory config', function () {
|
2
|
+
'use strict';
|
3
|
+
|
4
|
+
it('should allow disabling root wrapping globally', function () {
|
5
|
+
module('rails', function (railsResourceFactoryProvider) {
|
6
|
+
expect(railsResourceFactoryProvider.enableRootWrapping(false)).toBe(railsResourceFactoryProvider);
|
7
|
+
});
|
8
|
+
|
9
|
+
inject(function (railsResourceFactory) {
|
10
|
+
expect(railsResourceFactory({name: 'test', url: '/test'}).enableRootWrapping).toBe(false);
|
11
|
+
});
|
12
|
+
});
|
13
|
+
|
14
|
+
it('should allow setting updateMethod globally', function () {
|
15
|
+
module('rails', function (railsResourceFactoryProvider) {
|
16
|
+
expect(railsResourceFactoryProvider.updateMethod('patch')).toBe(railsResourceFactoryProvider);
|
17
|
+
});
|
18
|
+
|
19
|
+
inject(function (railsResourceFactory) {
|
20
|
+
expect(railsResourceFactory({name: 'test', url: '/test'}).updateMethod).toBe('patch');
|
21
|
+
});
|
22
|
+
});
|
23
|
+
|
24
|
+
it('should allow setting http headers options globally', function () {
|
25
|
+
module('rails', function (railsResourceFactoryProvider) {
|
26
|
+
expect(railsResourceFactoryProvider.httpConfig({headers: {'test': "header"}})).toBe(railsResourceFactoryProvider);
|
27
|
+
});
|
28
|
+
|
29
|
+
inject(function (railsResourceFactory) {
|
30
|
+
expect(railsResourceFactory({name: 'test', url: '/test'}).httpConfig.headers).toEqualData({'Accept': 'application/json', 'Content-Type': 'application/json', 'test': 'header'});
|
31
|
+
});
|
32
|
+
});
|
33
|
+
|
34
|
+
it('should allow setting default query parameters options globally', function () {
|
35
|
+
module('rails', function (railsResourceFactoryProvider) {
|
36
|
+
expect(railsResourceFactoryProvider.defaultParams({'test': "1"})).toBe(railsResourceFactoryProvider);
|
37
|
+
});
|
38
|
+
|
39
|
+
inject(function (railsResourceFactory) {
|
40
|
+
expect(railsResourceFactory({name: 'test', url: '/test'}).defaultParams).toEqualData({'test': '1'});
|
41
|
+
});
|
42
|
+
});
|
43
|
+
});
|
@@ -228,6 +228,53 @@ describe('railsResourceFactory', function () {
|
|
228
228
|
expect(data).toEqualData({id: 123, abcDef: 'xyz', xyz: 'abc', extra: 'test'});
|
229
229
|
}));
|
230
230
|
|
231
|
+
it('should be able to create new instance and update it using PATCH', inject(function($httpBackend) {
|
232
|
+
var promise, Resource, data, defaultParamsConfig = {};
|
233
|
+
|
234
|
+
angular.copy(config, defaultParamsConfig);
|
235
|
+
defaultParamsConfig.updateMethod = 'patch';
|
236
|
+
|
237
|
+
Resource = factory(defaultParamsConfig);
|
238
|
+
data = new Resource({abcDef: 'xyz'});
|
239
|
+
|
240
|
+
$httpBackend.expectPOST('/test', {test: {abc_def: 'xyz'}}).respond(200, {test: {id: 123, abc_def: 'xyz'}});
|
241
|
+
data.create();
|
242
|
+
$httpBackend.flush(1);
|
243
|
+
|
244
|
+
expect(data).toEqualData({id: 123, abcDef: 'xyz'});
|
245
|
+
|
246
|
+
$httpBackend.expectPATCH('/test/123', {test: {abc_def: 'xyz', id: 123, xyz: 'abc'}}).respond(200, {test: {id: 123, abc_def: 'xyz', xyz: 'abc', extra: 'test'}});
|
247
|
+
data.xyz = 'abc';
|
248
|
+
data.update();
|
249
|
+
$httpBackend.flush();
|
250
|
+
|
251
|
+
expect(data).toEqualData({id: 123, abcDef: 'xyz', xyz: 'abc', extra: 'test'});
|
252
|
+
}));
|
253
|
+
|
254
|
+
it('should be able to create new instance and update it using save using PATCH', inject(function($httpBackend) {
|
255
|
+
var promise, Resource, data, defaultParamsConfig = {};
|
256
|
+
|
257
|
+
angular.copy(config, defaultParamsConfig);
|
258
|
+
defaultParamsConfig.updateMethod = 'patch';
|
259
|
+
|
260
|
+
Resource = factory(defaultParamsConfig);
|
261
|
+
data = new Resource({abcDef: 'xyz'});
|
262
|
+
|
263
|
+
$httpBackend.expectPOST('/test', {test: {abc_def: 'xyz'}}).respond(200, {test: {id: 123, abc_def: 'xyz'}});
|
264
|
+
data.save();
|
265
|
+
$httpBackend.flush(1);
|
266
|
+
|
267
|
+
expect(data).toEqualData({id: 123, abcDef: 'xyz'});
|
268
|
+
|
269
|
+
$httpBackend.expectPATCH('/test/123', {test: {abc_def: 'xyz', id: 123, xyz: 'abc'}}).respond(200, {test: {id: 123, abc_def: 'xyz', xyz: 'abc', extra: 'test'}});
|
270
|
+
data.xyz = 'abc';
|
271
|
+
data.save();
|
272
|
+
$httpBackend.flush();
|
273
|
+
|
274
|
+
expect(data).toEqualData({id: 123, abcDef: 'xyz', xyz: 'abc', extra: 'test'});
|
275
|
+
}));
|
276
|
+
|
277
|
+
|
231
278
|
it('create with default params should add parameter abc=1', inject(function($httpBackend) {
|
232
279
|
var promise, Resource, data, defaultParamsConfig = {};
|
233
280
|
|
@@ -1,333 +1,395 @@
|
|
1
|
-
describe('
|
1
|
+
describe('railsSerializer', function () {
|
2
2
|
'use strict';
|
3
|
-
var factory, railsInjector;
|
4
3
|
|
5
|
-
function
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
4
|
+
describe('provider config', function () {
|
5
|
+
it('should allow overriding underscore method', function () {
|
6
|
+
var overrideCalled = false;
|
7
|
+
|
8
|
+
module('rails', function (railsSerializerProvider) {
|
9
|
+
expect(railsSerializerProvider.underscore(function (value) {
|
10
|
+
overrideCalled = true;
|
11
|
+
return value;
|
12
|
+
})).toBe(railsSerializerProvider);
|
13
|
+
});
|
14
|
+
|
15
|
+
inject(function (railsSerializer, RailsResourceInjector) {
|
16
|
+
var test = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'};
|
17
|
+
expect(RailsResourceInjector.createService(railsSerializer()).serialize(test)).toEqualData(test);
|
18
|
+
expect(overrideCalled).toBeTruthy();
|
19
|
+
});
|
21
20
|
});
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
it('should allow overriding camelize method', function () {
|
23
|
+
var overrideCalled = false;
|
24
|
+
|
25
|
+
module('rails', function (railsSerializerProvider) {
|
26
|
+
expect(railsSerializerProvider.camelize(function (value) {
|
27
|
+
overrideCalled = true;
|
28
|
+
return value;
|
29
|
+
})).toBe(railsSerializerProvider);
|
30
|
+
});
|
31
|
+
|
32
|
+
inject(function (railsSerializer, RailsResourceInjector) {
|
33
|
+
var test = {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'};
|
34
|
+
expect(RailsResourceInjector.createService(railsSerializer()).deserialize(test)).toEqualData(test);
|
35
|
+
expect(overrideCalled).toBeTruthy();
|
36
|
+
});
|
31
37
|
});
|
32
38
|
|
33
|
-
|
39
|
+
it('should allow overriding pluralize method', function () {
|
40
|
+
module('rails', function (railsSerializerProvider) {
|
41
|
+
expect(railsSerializerProvider.pluralize(function (value) {
|
42
|
+
return value + 'ies';
|
43
|
+
})).toBe(railsSerializerProvider);
|
44
|
+
});
|
34
45
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
var serializer;
|
39
|
-
|
40
|
-
beforeEach(function () {
|
41
|
-
serializer = createSerializer();
|
42
|
-
});
|
43
|
-
|
44
|
-
it('should underscore attributes on single object', function () {
|
45
|
-
var orig = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'},
|
46
|
-
result = serializer.serialize(orig);
|
47
|
-
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
48
|
-
result = serializer.deserialize(result);
|
49
|
-
expect(result).toEqualData(orig);
|
46
|
+
inject(function (railsSerializer, RailsResourceInjector) {
|
47
|
+
expect(RailsResourceInjector.createService(railsSerializer()).pluralize('cook')).toEqual('cookies');
|
48
|
+
});
|
50
49
|
});
|
51
50
|
|
52
|
-
it('should
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
result = serializer.deserialize(result);
|
57
|
-
expect(result).toEqualData(orig);
|
58
|
-
});
|
59
|
-
|
60
|
-
it('should underscore attribute inside array objects', function () {
|
61
|
-
var orig = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', books: [
|
62
|
-
{id: 1, title: 'A Game of Thrones', publicationDate: '1996-08-06'}
|
63
|
-
]},
|
64
|
-
result = serializer.serialize(orig);
|
65
|
-
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', books: [
|
66
|
-
{id: 1, title: 'A Game of Thrones', publication_date: '1996-08-06'}
|
67
|
-
]});
|
68
|
-
result = serializer.deserialize(result);
|
69
|
-
expect(result).toEqualData(orig);
|
70
|
-
});
|
51
|
+
it('should allow overriding exclusionMatchers method', function () {
|
52
|
+
module('rails', function (railsSerializerProvider) {
|
53
|
+
expect(railsSerializerProvider.exclusionMatchers(['_'])).toBe(railsSerializerProvider);
|
54
|
+
});
|
71
55
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
result = serializer.deserialize(result);
|
77
|
-
expect(result).toEqualData(orig);
|
56
|
+
inject(function (railsSerializer, RailsResourceInjector) {
|
57
|
+
var test = {id: 1, _firstName: 'George', _middleName: 'R. R.', lastName: 'Martin'};
|
58
|
+
expect(RailsResourceInjector.createService(railsSerializer()).serialize(test)).toEqualData({id: 1, last_name: 'Martin'});
|
59
|
+
});
|
78
60
|
});
|
79
|
-
|
80
|
-
it('should exclude attributes that start with $', function () {
|
81
|
-
var result = serializer.serialize({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
82
|
-
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
83
|
-
result = serializer.deserialize({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'});
|
84
|
-
expect(result).toEqualData({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'});
|
85
|
-
});
|
86
|
-
|
87
|
-
it('should exclude functions', function () {
|
88
|
-
var result = serializer.serialize({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $books: [], getNumBooks: function () {
|
89
|
-
this.$books.length
|
90
|
-
}});
|
91
|
-
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
92
|
-
});
|
93
|
-
|
94
61
|
});
|
95
62
|
|
96
|
-
describe('
|
97
|
-
|
98
|
-
var test,
|
99
|
-
serializer = createSerializer({underscore: undefined, camelize: undefined});
|
100
|
-
|
101
|
-
test = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'};
|
102
|
-
expect(serializer.serialize(test)).toEqualData(test);
|
103
|
-
test = {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'};
|
104
|
-
expect(serializer.deserialize(test)).toEqualData(test);
|
105
|
-
});
|
63
|
+
describe('default provider options', function () {
|
64
|
+
var factory, railsInjector;
|
106
65
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
underscore: function (attribute) {
|
111
|
-
return 'x' + attribute
|
112
|
-
},
|
113
|
-
camelize: function (attribute) {
|
114
|
-
return 'y' + attribute
|
115
|
-
}
|
116
|
-
});
|
66
|
+
function createSerializer(options, customizer) {
|
67
|
+
return railsInjector.createService(factory(options, customizer));
|
68
|
+
}
|
117
69
|
|
118
|
-
|
119
|
-
expect(result).toEqualData({xid: 1, xfirstName: 'George', xmiddleName: 'R. R.', xlastName: 'Martin'});
|
120
|
-
result = serializer.deserialize({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
121
|
-
expect(result).toEqualData({yid: 1, yfirst_name: 'George', ymiddle_name: 'R. R.', ylast_name: 'Martin'});
|
122
|
-
});
|
70
|
+
beforeEach(module('rails'));
|
123
71
|
|
124
|
-
|
125
|
-
|
126
|
-
|
72
|
+
beforeEach(inject(function (railsSerializer, RailsResourceInjector) {
|
73
|
+
factory = railsSerializer;
|
74
|
+
railsInjector = RailsResourceInjector;
|
75
|
+
}));
|
127
76
|
|
128
|
-
|
129
|
-
|
130
|
-
result = serializer.serialize(camelized);
|
131
|
-
expect(result).toEqualData(underscored);
|
132
|
-
result = serializer.deserialize(underscored);
|
133
|
-
expect(result).toEqualData(camelized);
|
134
|
-
});
|
77
|
+
describe('default config', function () {
|
78
|
+
var serializer;
|
135
79
|
|
136
|
-
|
137
|
-
|
138
|
-
|
80
|
+
beforeEach(function () {
|
81
|
+
serializer = createSerializer();
|
82
|
+
});
|
139
83
|
|
140
|
-
|
141
|
-
|
142
|
-
result = serializer.serialize(camelized);
|
143
|
-
expect(result).toEqualData(underscored);
|
144
|
-
result = serializer.deserialize(underscored);
|
145
|
-
expect(result).toEqualData(camelized);
|
146
|
-
});
|
84
|
+
it('should support customizer being first parameter', function () {
|
85
|
+
var called = false;
|
147
86
|
|
148
|
-
|
149
|
-
|
150
|
-
|
87
|
+
createSerializer(function () {
|
88
|
+
called = true;
|
89
|
+
});
|
151
90
|
|
152
|
-
|
153
|
-
|
154
|
-
result = serializer.serialize(camelized);
|
155
|
-
expect(result).toEqualData(underscored);
|
156
|
-
result = serializer.deserialize(underscored);
|
157
|
-
expect(result).toEqualData(camelized);
|
158
|
-
});
|
91
|
+
expect(called).toBeTruthy();
|
92
|
+
});
|
159
93
|
|
160
|
-
|
161
|
-
|
162
|
-
serializer = createSerializer({exclusionMatchers: ['x']});
|
94
|
+
it('should support customizer with options as first parameter', function () {
|
95
|
+
var called = false;
|
163
96
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
expect(result).toEqualData({xid: 1, firstNamex: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
168
|
-
});
|
97
|
+
createSerializer({}, function () {
|
98
|
+
called = true;
|
99
|
+
});
|
169
100
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
101
|
+
expect(called).toBeTruthy();
|
102
|
+
|
103
|
+
});
|
104
|
+
|
105
|
+
it('should underscore attributes on single object', function () {
|
106
|
+
var orig = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'},
|
107
|
+
result = serializer.serialize(orig);
|
108
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
109
|
+
result = serializer.deserialize(result);
|
110
|
+
expect(result).toEqualData(orig);
|
111
|
+
});
|
112
|
+
|
113
|
+
it('should underscore attributes on nested objects', function () {
|
114
|
+
var orig = {id: 6, title: 'Winds of Winter', pages: 1105, publicationDate: '2020-05-25', author: {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'}},
|
115
|
+
result = serializer.serialize(orig);
|
116
|
+
expect(result).toEqualData({id: 6, title: 'Winds of Winter', pages: 1105, publication_date: '2020-05-25', author: {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'}});
|
117
|
+
result = serializer.deserialize(result);
|
118
|
+
expect(result).toEqualData(orig);
|
119
|
+
});
|
120
|
+
|
121
|
+
it('should underscore attribute inside array objects', function () {
|
122
|
+
var orig = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', books: [
|
123
|
+
{id: 1, title: 'A Game of Thrones', publicationDate: '1996-08-06'}
|
124
|
+
]},
|
125
|
+
result = serializer.serialize(orig);
|
126
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', books: [
|
127
|
+
{id: 1, title: 'A Game of Thrones', publication_date: '1996-08-06'}
|
128
|
+
]});
|
129
|
+
result = serializer.deserialize(result);
|
130
|
+
expect(result).toEqualData(orig);
|
131
|
+
});
|
132
|
+
|
133
|
+
it('should support primitive arrays', function () {
|
134
|
+
var orig = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', books: [1, 2, 3]},
|
135
|
+
result = serializer.serialize(orig);
|
136
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', books: [1, 2, 3]});
|
137
|
+
result = serializer.deserialize(result);
|
138
|
+
expect(result).toEqualData(orig);
|
139
|
+
});
|
140
|
+
|
141
|
+
it('should exclude attributes that start with $', function () {
|
142
|
+
var result = serializer.serialize({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
143
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
144
|
+
result = serializer.deserialize({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'});
|
145
|
+
expect(result).toEqualData({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'});
|
146
|
+
});
|
147
|
+
|
148
|
+
it('should exclude functions', function () {
|
149
|
+
var result = serializer.serialize({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $books: [], getNumBooks: function () {
|
150
|
+
this.$books.length
|
151
|
+
}});
|
152
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
153
|
+
});
|
175
154
|
|
176
|
-
result = serializer.serialize({xid: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
177
|
-
expect(result).toEqualData({first_name: 'George', last_name: 'Martin'});
|
178
|
-
result = serializer.deserialize({xid: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'});
|
179
|
-
expect(result).toEqualData({xid: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birth_date: '1948-09-20'});
|
180
155
|
});
|
181
|
-
});
|
182
156
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
lastName: 'Martin'
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
]
|
205
|
-
};
|
206
|
-
|
207
|
-
it('should allow single exclusion', function () {
|
208
|
-
var result,
|
209
|
-
serializer = createSerializer(function (config) {
|
210
|
-
config.exclude('books');
|
211
|
-
});
|
157
|
+
describe('custom options', function () {
|
158
|
+
it('should allow overriding attribute transformation functions with undefined', function () {
|
159
|
+
var test,
|
160
|
+
serializer = createSerializer({underscore: undefined, camelize: undefined});
|
161
|
+
|
162
|
+
test = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'};
|
163
|
+
expect(serializer.serialize(test)).toEqualData(test);
|
164
|
+
test = {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'};
|
165
|
+
expect(serializer.deserialize(test)).toEqualData(test);
|
166
|
+
});
|
167
|
+
|
168
|
+
it('should allow overriding attribute transformation with custom function', function () {
|
169
|
+
var result,
|
170
|
+
serializer = createSerializer({
|
171
|
+
underscore: function (attribute) {
|
172
|
+
return 'x' + attribute
|
173
|
+
},
|
174
|
+
camelize: function (attribute) {
|
175
|
+
return 'y' + attribute
|
176
|
+
}
|
177
|
+
});
|
212
178
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
179
|
+
result = serializer.serialize({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'});
|
180
|
+
expect(result).toEqualData({xid: 1, xfirstName: 'George', xmiddleName: 'R. R.', xlastName: 'Martin'});
|
181
|
+
result = serializer.deserialize({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
182
|
+
expect(result).toEqualData({yid: 1, yfirst_name: 'George', ymiddle_name: 'R. R.', ylast_name: 'Martin'});
|
183
|
+
});
|
184
|
+
|
185
|
+
it('should allow safely ignore null excludePrefixes', function () {
|
186
|
+
var result, underscored, camelized,
|
187
|
+
serializer = createSerializer({exclusionMatchers: null});
|
188
|
+
|
189
|
+
camelized = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'};
|
190
|
+
underscored = {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'};
|
191
|
+
result = serializer.serialize(camelized);
|
192
|
+
expect(result).toEqualData(underscored);
|
193
|
+
result = serializer.deserialize(underscored);
|
194
|
+
expect(result).toEqualData(camelized);
|
195
|
+
});
|
196
|
+
|
197
|
+
it('should allow safely ignore undefined excludePrefixes', function () {
|
198
|
+
var result, underscored, camelized,
|
199
|
+
serializer = createSerializer({exclusionMatchers: undefined});
|
200
|
+
|
201
|
+
camelized = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'};
|
202
|
+
underscored = {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'};
|
203
|
+
result = serializer.serialize(camelized);
|
204
|
+
expect(result).toEqualData(underscored);
|
205
|
+
result = serializer.deserialize(underscored);
|
206
|
+
expect(result).toEqualData(camelized);
|
207
|
+
});
|
208
|
+
|
209
|
+
it('should allow empty excludePrefixes', function () {
|
210
|
+
var result, underscored, camelized,
|
211
|
+
serializer = createSerializer({exclusionMatchers: []});
|
212
|
+
|
213
|
+
camelized = {id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'};
|
214
|
+
underscored = {id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'};
|
215
|
+
result = serializer.serialize(camelized);
|
216
|
+
expect(result).toEqualData(underscored);
|
217
|
+
result = serializer.deserialize(underscored);
|
218
|
+
expect(result).toEqualData(camelized);
|
219
|
+
});
|
220
|
+
|
221
|
+
it('should treat exclusionMatcher strings as prefix exclusions', function () {
|
222
|
+
var result,
|
223
|
+
serializer = createSerializer({exclusionMatchers: ['x']});
|
224
|
+
|
225
|
+
result = serializer.serialize({xid: 1, firstNamex: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
226
|
+
expect(result).toEqualData({first_namex: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'});
|
227
|
+
result = serializer.deserialize({xid: 1, first_namex: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'});
|
228
|
+
expect(result).toEqualData({xid: 1, firstNamex: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
229
|
+
});
|
230
|
+
|
231
|
+
it('should use combination of string prefix, function, and regexp for exclusions', function () {
|
232
|
+
var result,
|
233
|
+
serializer = createSerializer({exclusionMatchers: ['x', /^$/, function (key) {
|
234
|
+
return key === 'middleName';
|
235
|
+
}]});
|
236
|
+
|
237
|
+
result = serializer.serialize({xid: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birthDate: '1948-09-20'});
|
238
|
+
expect(result).toEqualData({first_name: 'George', last_name: 'Martin'});
|
239
|
+
result = serializer.deserialize({xid: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', $birth_date: '1948-09-20'});
|
240
|
+
expect(result).toEqualData({xid: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin', $birth_date: '1948-09-20'});
|
241
|
+
});
|
217
242
|
});
|
218
243
|
|
219
|
-
|
220
|
-
var
|
221
|
-
|
222
|
-
|
223
|
-
|
244
|
+
describe('customized serialization', function () {
|
245
|
+
var camelizedAuthor = {
|
246
|
+
id: 1,
|
247
|
+
firstName: 'George',
|
248
|
+
middleName: 'R. R.',
|
249
|
+
lastName: 'Martin',
|
250
|
+
birthDate: '1948-09-20',
|
251
|
+
books: [
|
252
|
+
{id: 1, title: 'A Game of Thrones', pages: 694, series: 'A Song of Ice and Fire', publicationDate: '1996-08-06', authorId: 1},
|
253
|
+
{id: 2, title: 'A Clash of Kings', pages: 768, series: 'A Song of Ice and Fire', publicationDate: '1999-03-01', authorId: 1},
|
254
|
+
]
|
255
|
+
},
|
256
|
+
underscoredAuthor = {
|
257
|
+
id: 1,
|
258
|
+
first_name: 'George',
|
259
|
+
middle_name: 'R. R.',
|
260
|
+
last_name: 'Martin',
|
261
|
+
birth_date: '1948-09-20',
|
262
|
+
books: [
|
263
|
+
{id: 1, title: 'A Game of Thrones', pages: 694, series: 'A Song of Ice and Fire', publication_date: '1996-08-06', author_id: 1},
|
264
|
+
{id: 2, title: 'A Clash of Kings', pages: 768, series: 'A Song of Ice and Fire', publication_date: '1999-03-01', author_id: 1},
|
265
|
+
]
|
266
|
+
};
|
267
|
+
|
268
|
+
it('should allow single exclusion', function () {
|
269
|
+
var result,
|
270
|
+
serializer = createSerializer(function (config) {
|
271
|
+
config.exclude('books');
|
272
|
+
});
|
224
273
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
274
|
+
result = serializer.serialize(camelizedAuthor);
|
275
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin', birth_date: '1948-09-20'});
|
276
|
+
result = serializer.deserialize(underscoredAuthor);
|
277
|
+
expect(result).toEqualData(camelizedAuthor);
|
278
|
+
});
|
230
279
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
this.rename('id', 'authorId');
|
237
|
-
this.rename('firstName', 'first');
|
238
|
-
this.rename('middleName', 'middle');
|
239
|
-
config.rename('lastName', 'last');
|
240
|
-
});
|
280
|
+
it('should allow variable exclusions', function () {
|
281
|
+
var result,
|
282
|
+
serializer = createSerializer(function (config) {
|
283
|
+
config.exclude('books', 'birthDate');
|
284
|
+
});
|
241
285
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
286
|
+
result = serializer.serialize(camelizedAuthor);
|
287
|
+
expect(result).toEqualData({id: 1, first_name: 'George', middle_name: 'R. R.', last_name: 'Martin'});
|
288
|
+
result = serializer.deserialize(underscoredAuthor);
|
289
|
+
expect(result).toEqualData(camelizedAuthor);
|
290
|
+
});
|
291
|
+
|
292
|
+
it('should allow renaming attributes', function () {
|
293
|
+
var result,
|
294
|
+
serializer = createSerializer(function (config) {
|
295
|
+
// this & config should be interchangeable
|
296
|
+
this.exclude('books', 'birthDate');
|
297
|
+
this.rename('id', 'authorId');
|
298
|
+
this.rename('firstName', 'first');
|
299
|
+
this.rename('middleName', 'middle');
|
300
|
+
config.rename('lastName', 'last');
|
301
|
+
});
|
247
302
|
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
303
|
+
result = serializer.serialize(camelizedAuthor);
|
304
|
+
expect(result).toEqualData({author_id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
305
|
+
result = serializer.deserialize({author_id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
306
|
+
expect(result).toEqualData({id: 1, firstName: 'George', middleName: 'R. R.', lastName: 'Martin'});
|
307
|
+
});
|
253
308
|
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
result = serializer.deserialize(underscoredAuthor);
|
260
|
-
expect(result).toEqualData(camelizedAuthor);
|
261
|
-
});
|
309
|
+
it('should allow nested attributes', function () {
|
310
|
+
var result,
|
311
|
+
serializer = createSerializer(function () {
|
312
|
+
this.nestedAttribute('books')
|
313
|
+
});
|
262
314
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
315
|
+
result = serializer.serialize(camelizedAuthor);
|
316
|
+
expect(result['books_attributes']).toEqualData([
|
317
|
+
{id: 1, title: 'A Game of Thrones', pages: 694, series: 'A Song of Ice and Fire', publication_date: '1996-08-06', author_id: 1},
|
318
|
+
{id: 2, title: 'A Clash of Kings', pages: 768, series: 'A Song of Ice and Fire', publication_date: '1999-03-01', author_id: 1}
|
319
|
+
]);
|
320
|
+
result = serializer.deserialize(underscoredAuthor);
|
321
|
+
expect(result).toEqualData(camelizedAuthor);
|
322
|
+
});
|
323
|
+
|
324
|
+
it('should add custom attribute from function', function () {
|
325
|
+
var result,
|
326
|
+
serializer = createSerializer(function () {
|
327
|
+
this.add('numBooks', function (author) {
|
328
|
+
return author.books.length;
|
329
|
+
});
|
268
330
|
});
|
269
|
-
});
|
270
331
|
|
271
|
-
|
272
|
-
|
273
|
-
|
332
|
+
result = serializer.serialize(camelizedAuthor);
|
333
|
+
expect(result['num_books']).toBe(2);
|
334
|
+
});
|
274
335
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
336
|
+
it('should add custom attribute from constant value', function () {
|
337
|
+
var result,
|
338
|
+
serializer = createSerializer(function () {
|
339
|
+
this.add('numBooks', 2);
|
340
|
+
});
|
280
341
|
|
281
|
-
|
282
|
-
|
283
|
-
|
342
|
+
result = serializer.serialize(camelizedAuthor);
|
343
|
+
expect(result['num_books']).toBe(2);
|
344
|
+
});
|
284
345
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
346
|
+
it('should use custom serializer for books', function () {
|
347
|
+
var result, serializedBooks, underscored,
|
348
|
+
serializer = createSerializer(function () {
|
349
|
+
this.serializeWith('books', factory(function () {
|
350
|
+
this.rename('publicationDate', 'published');
|
351
|
+
}));
|
352
|
+
});
|
292
353
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
354
|
+
result = serializer.serialize(camelizedAuthor);
|
355
|
+
serializedBooks = [
|
356
|
+
{id: 1, title: 'A Game of Thrones', pages: 694, series: 'A Song of Ice and Fire', published: '1996-08-06', author_id: 1},
|
357
|
+
{id: 2, title: 'A Clash of Kings', pages: 768, series: 'A Song of Ice and Fire', published: '1999-03-01', author_id: 1}
|
358
|
+
];
|
359
|
+
|
360
|
+
expect(result['books']).toEqualData(serializedBooks);
|
361
|
+
underscored = angular.copy(underscoredAuthor);
|
362
|
+
underscored['books'] = serializedBooks;
|
363
|
+
result = serializer.deserialize(underscored);
|
364
|
+
expect(result).toEqualData(camelizedAuthor);
|
365
|
+
});
|
304
366
|
});
|
305
|
-
});
|
306
367
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
368
|
+
describe('default exclusion serialization', function () {
|
369
|
+
it('should only serialize id', function () {
|
370
|
+
var result,
|
371
|
+
serializer = createSerializer(function (config) {
|
372
|
+
// this & config should be interchangeable
|
373
|
+
this.only('id');
|
374
|
+
});
|
314
375
|
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
376
|
+
result = serializer.serialize({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
377
|
+
expect(result).toEqualData({id: 1});
|
378
|
+
result = serializer.deserialize({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
379
|
+
expect(result).toEqualData({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
380
|
+
});
|
320
381
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
382
|
+
it('should only serialize id and last', function () {
|
383
|
+
var result,
|
384
|
+
serializer = createSerializer(function (config) {
|
385
|
+
this.only('id', 'last');
|
386
|
+
});
|
326
387
|
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
388
|
+
result = serializer.serialize({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
389
|
+
expect(result).toEqualData({id: 1, last: 'Martin'});
|
390
|
+
result = serializer.deserialize({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
391
|
+
expect(result).toEqualData({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
392
|
+
});
|
331
393
|
});
|
332
394
|
});
|
333
395
|
});
|