angularjs-rails-resource 1.0.0.pre.1 → 1.0.0.pre.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/EXAMPLES.md +116 -116
- data/angularjs-rails-resource.js +19 -6
- data/angularjs-rails-resource.min.js +2 -2
- data/angularjs-rails-resource.zip +0 -0
- data/bower.json +1 -1
- data/lib/angularjs-rails-resource/version.rb +1 -1
- data/package.json +1 -1
- data/test/unit/angularjs/rails/resourceSpec.js +8 -0
- data/test/unit/angularjs/rails/serializationSpec.js +16 -0
- data/vendor/assets/javascripts/angularjs/rails/resource/resource.js +6 -2
- data/vendor/assets/javascripts/angularjs/rails/resource/serialization.js +12 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e088a0ef4c31ca6952015c7e5bf25e29a3aeffa6
|
4
|
+
data.tar.gz: ceafd0fc62d19853922b36a79b3926cd1ca579c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8715afd2c22e4a5341512ba1845d83c6b5044cb6592dec4574fe530f908866ad9a48cc9f51b1fcfefe977bd30cf8661e5e39f2240c61ed9a0237be1cb81a6e28
|
7
|
+
data.tar.gz: 93efebbbb2920fe2f2d6deb883bdfbe18cb8e5a720e93c946471deb1b9e8d6794820421e1dd4589179fc9643fb2c0eed90261458dbea030f05b291deda8f894c
|
data/EXAMPLES.md
CHANGED
@@ -7,74 +7,74 @@ For example, suppose we have an Author that serializes all of the books that aut
|
|
7
7
|
are a nested resource that allows us to more easily perform updates against those books without having to worry about creating
|
8
8
|
a resource instance for the book.
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
10
|
+
angular.module('book.services', ['rails']);
|
11
|
+
|
12
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', function (railsResourceFactory) {
|
13
|
+
return railsResourceFactory({url: '/books', name: 'book'});
|
14
|
+
}]);
|
15
|
+
|
16
|
+
angular.module('book.services').factory('Author', ['railsResourceFactory', 'railsSerializer', function (railsResourceFactory, railsSerializer) {
|
17
|
+
return railsResourceFactory({
|
18
|
+
url: '/authors',
|
19
|
+
name: 'author',
|
20
|
+
serializer: railsSerializer(function () {
|
21
|
+
this.resource('books', 'Book');
|
22
|
+
})
|
23
|
+
});
|
24
|
+
}]);
|
25
|
+
|
26
|
+
angular.module('book.controllers').controller('AuthorCtrl', ['$scope', 'Author', function ($scope, Author) {
|
27
|
+
$scope.author = Author.get(123);
|
28
|
+
|
29
|
+
// allow the view to trigger an update to a book from $scope.author.books
|
30
|
+
$scope.updateBook = function (book) {
|
31
|
+
book.update();
|
32
|
+
}
|
33
|
+
}]);
|
34
34
|
|
35
35
|
# Nested attributes
|
36
36
|
While we don't have logic for full nested attributes support, the new serializer does allow you to specify which fields
|
37
37
|
should be passed with the <code>_attributes</code> suffix.
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
39
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', 'railsSerializer', function (railsResourceFactory, railsSerializer) {
|
40
|
+
return railsResourceFactory({
|
41
|
+
url: '/books',
|
42
|
+
name: 'book',
|
43
|
+
serializer: railsSerializer(function () {
|
44
|
+
this.nestedAttribute('author');
|
45
|
+
})
|
46
|
+
});
|
47
|
+
}]);
|
48
48
|
|
49
49
|
# Excluding attributes from serialization
|
50
50
|
Sometimes you don't want to serialize certain fields when updating an object. Take for instance the case of the author on a book.
|
51
51
|
We know that we don't accept nested attributes for the author on the server so we want to exclude it from the JSON to reduce
|
52
52
|
the amount of data being sent to the server.
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
54
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', 'railsSerializer', function (railsResourceFactory railsSerializer) {
|
55
|
+
return railsResourceFactory({
|
56
|
+
url: '/books',
|
57
|
+
name: 'book',
|
58
|
+
serializer: railsSerializer(function () {
|
59
|
+
this.exclude('author');
|
60
|
+
})
|
61
|
+
});
|
62
|
+
}]);
|
63
63
|
|
64
64
|
|
65
65
|
# Only allowing specific attributes for serialization
|
66
66
|
You can also be very restrictive and only include specific attributes that you want to send to the server. All other attribtues
|
67
67
|
would be excluded by default.
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', 'railsSerializer', function (railsResourceFactory. railsSerializer) {
|
70
|
+
return railsResourceFactory({
|
71
|
+
url: '/books',
|
72
|
+
name: 'book',
|
73
|
+
serializer: railsSerializer(function () {
|
74
|
+
this.only('id', 'isbn', 'publicationDate');
|
75
|
+
})
|
76
|
+
});
|
77
|
+
}]);
|
78
78
|
|
79
79
|
|
80
80
|
# Adding custom methods to a resource
|
@@ -84,61 +84,61 @@ You can add additional "class" or "instance" methods by modifying the resource r
|
|
84
84
|
For instance, if you wanted to add a method that would search for Books by the title without having to construct the query params
|
85
85
|
each time you could add a new <code>findByTitle</code> class function.
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
87
|
+
angular.module('book.services', ['rails']);
|
88
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', function (railsResourceFactory) {
|
89
|
+
var resource = railsResourceFactory({url: '/books', name: 'book'});
|
90
|
+
resource.findByTitle = function (title) {
|
91
|
+
return resource.query({title: title});
|
92
|
+
};
|
93
|
+
return resource;
|
94
|
+
}]);
|
95
|
+
|
96
|
+
angular.module('book.controllers').controller('BookShelfCtrl', ['$scope', 'Book', function ($scope, Book) {
|
97
|
+
$scope.searching = true;
|
98
|
+
// Find all books matching the title
|
99
|
+
$scope.books = Book.findByTitle({title: title});
|
100
|
+
$scope.books.then(function(results) {
|
101
|
+
$scope.searching = false;
|
102
|
+
}, function (error) {
|
103
|
+
$scope.searching = false;
|
104
|
+
});
|
105
|
+
}]);
|
106
106
|
|
107
107
|
## Get related object
|
108
108
|
You can also add additional methods on the object prototype chain so all instances of the resource have that function available.
|
109
109
|
The following example exposes a <code>getAuthor</code> instance method that would be accessible on all Book instances.
|
110
110
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
111
|
+
angular.module('book.services', ['rails']);
|
112
|
+
angular.module('book.services').factory('Author', ['railsResourceFactory', function (railsResourceFactory) {
|
113
|
+
return railsResourceFactory({url: '/authors', name: 'author'});
|
114
|
+
}]);
|
115
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', 'Author', function (railsResourceFactory, Author) {
|
116
|
+
var resource = railsResourceFactory({url: '/books', name: 'book'});
|
117
|
+
resource.prototype.getAuthor = function () {
|
118
|
+
return Author.get(this.authorId);
|
119
|
+
};
|
120
|
+
}]);
|
121
|
+
angular.module('book.controllers').controller('BookShelfCtrl', ['$scope', 'Book', function ($scope, Book) {
|
122
|
+
$scope.getAuthorDetails = function (book) {
|
123
|
+
$scope.author = book.getAuthor();
|
124
|
+
};
|
125
|
+
}]);
|
126
126
|
|
127
127
|
## Nested URL
|
128
128
|
Or say you instead had a nested "references" service call that returned a list of referenced books for a given book instance. In that case you can add your own addition method that calls $http.get and then
|
129
129
|
passes the resulting promise to the processResponse method which will perform the same transformations and handling that the get or query would use.
|
130
130
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
131
|
+
angular.module('book.services', ['rails']);
|
132
|
+
angular.module('book.services').factory('Book', ['railsResourceFactory', '$http', function (railsResourceFactory, $http) {
|
133
|
+
var resource = railsResourceFactory({url: '/books', name: 'book'});
|
134
|
+
resource.prototype.getReferences = function () {
|
135
|
+
var self = this;
|
136
|
+
return resource.$get(self.$url('references'))).then(function (references) {
|
137
|
+
self.references = references;
|
138
|
+
return self.references;
|
139
|
+
});
|
140
|
+
};
|
141
|
+
}]);
|
142
142
|
|
143
143
|
# Specifying Transformer
|
144
144
|
Transformers can be specified by an array of transformers in the configuration options passed to railsResourceFactory.
|
@@ -147,25 +147,25 @@ a function returned by a factory if you want to share a transformer across multi
|
|
147
147
|
|
148
148
|
Both of these examples can be accomplished using the serializers now.
|
149
149
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
150
|
+
angular.module('test').factory('excludePrivateKeysTransformer', function () {
|
151
|
+
return function (data) {
|
152
|
+
angular.forEach(data, function (value, key) {
|
153
|
+
if (key[0] === '_') {
|
154
|
+
delete data[key];
|
155
|
+
}
|
156
|
+
});
|
157
|
+
});
|
158
|
+
});
|
159
|
+
|
160
|
+
angular.module('test').factory('Book', function (railsResourceFactory, excludePrivateKeysTransformer) {
|
161
|
+
var Book = railsResourceFactory({url: '/books', name: 'book'});
|
162
|
+
Book.beforeRequest(excludePrivateKeysTransformer);
|
163
|
+
Book.beforeRequest(function (data) {
|
164
|
+
data['release_date'] = data['publicationDate'];
|
165
|
+
delete data['publicationDate'];
|
166
|
+
});
|
167
|
+
|
168
|
+
return Book;
|
169
|
+
});
|
170
170
|
|
171
171
|
|
data/angularjs-rails-resource.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/**
|
2
2
|
* A resource factory inspired by $resource from AngularJS
|
3
|
-
* @version v1.0.0-
|
3
|
+
* @version v1.0.0-pre.2 - 2013-11-24
|
4
4
|
* @link https://github.com/FineLinePrototyping/angularjs-rails-resource.git
|
5
5
|
* @author
|
6
6
|
*/
|
@@ -408,8 +408,17 @@
|
|
408
408
|
Serializer.prototype.getSerializedAttributeName = function (attributeName) {
|
409
409
|
var mappedName = this.serializeMappings[attributeName] || attributeName;
|
410
410
|
|
411
|
-
|
412
|
-
|
411
|
+
var mappedNameExcluded = this.isExcludedFromSerialization(mappedName),
|
412
|
+
attributeNameExcluded = this.isExcludedFromSerialization(attributeName);
|
413
|
+
|
414
|
+
if(this.options.excludeByDefault) {
|
415
|
+
if(mappedNameExcluded && attributeNameExcluded) {
|
416
|
+
return undefined;
|
417
|
+
}
|
418
|
+
} else {
|
419
|
+
if (mappedNameExcluded || attributeNameExcluded) {
|
420
|
+
return undefined;
|
421
|
+
}
|
413
422
|
}
|
414
423
|
|
415
424
|
return this.underscore(mappedName);
|
@@ -474,7 +483,7 @@
|
|
474
483
|
|
475
484
|
// custom serializer takes precedence over resource serializer
|
476
485
|
if (serializer) {
|
477
|
-
return RailsResourceInjector.createService(serializer)
|
486
|
+
return RailsResourceInjector.createService(serializer);
|
478
487
|
} else if (resource) {
|
479
488
|
return resource.config.serializer;
|
480
489
|
}
|
@@ -825,7 +834,11 @@
|
|
825
834
|
}
|
826
835
|
|
827
836
|
this.config.name = this.config.serializer.underscore(cfg.name);
|
828
|
-
|
837
|
+
|
838
|
+
// we don't want to turn undefined name into "undefineds" then the plural name won't update when the name is set
|
839
|
+
if (this.config.name) {
|
840
|
+
this.config.pluralName = this.config.serializer.underscore(cfg.pluralName || this.config.serializer.pluralize(this.config.name));
|
841
|
+
}
|
829
842
|
|
830
843
|
this.config.urlBuilder = railsUrlBuilder(this.config.url);
|
831
844
|
this.config.resourceConstructor = this;
|
@@ -1036,7 +1049,7 @@
|
|
1036
1049
|
RailsResource['$' + method] = function (url, data) {
|
1037
1050
|
var config;
|
1038
1051
|
// clone so we can manipulate w/o modifying the actual instance
|
1039
|
-
data = this.transformData(angular.copy(data
|
1052
|
+
data = this.transformData(angular.copy(data));
|
1040
1053
|
config = angular.extend({method: method, url: url, data: data}, this.getHttpConfig());
|
1041
1054
|
return this.processResponse($http(config));
|
1042
1055
|
};
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* A resource factory inspired by $resource from AngularJS
|
3
|
-
* @version v1.0.0-
|
3
|
+
* @version v1.0.0-pre.2 - 2013-11-24
|
4
4
|
* @link https://github.com/FineLinePrototyping/angularjs-rails-resource.git
|
5
5
|
* @author
|
6
6
|
*/
|
7
|
-
!function(){angular.module("rails",["ng"])}(),function(){angular.module("rails").factory("RailsInflector",function(){function a(a){return angular.isString(a)?a.replace(/_[\w\d]/g,function(a,b,c){return 0===b?a:c.charAt(b+1).toUpperCase()}):a}function b(a){return angular.isString(a)?a.replace(/[A-Z]/g,function(a,b){return 0===b?a:"_"+a.toLowerCase()}):a}function c(a){return a+"s"}return{camelize:a,underscore:b,pluralize:c}})}(),function(a){angular.module("rails").factory("RailsResourceInjector",["$injector",function(b){function c(c){return c?angular.isString(c)?b.get(c):c:a}function d(d){return d?b.instantiate(c(d)):a}return{createService:d,getDependency:c}}])}(),function(){angular.module("rails").factory("railsUrlBuilder",["$interpolate",function(a){return function(b){var c;return angular.isFunction(b)||angular.isUndefined(b)?b:(-1===b.indexOf(a.startSymbol())&&(b=b+"/"+a.startSymbol()+"id"+a.endSymbol()),c=a(b),function(a){return b=c(a),"/"===b.charAt(b.length-1)&&(b=b.substr(0,b.length-1)),b})}}])}(),function(a){angular.module("rails").provider("railsSerializer",function(){var b={underscore:a,camelize:a,pluralize:a,exclusionMatchers:[]};this.underscore=function(a){return b.underscore=a,this},this.camelize=function(a){return b.camelize=a,this},this.pluralize=function(a){return b.pluralize=a,this},this.exclusionMatchers=function(a){return b.exclusionMatchers=a,this},this.$get=["$injector","RailsInflector","RailsResourceInjector",function(c,d,e){function f(c,d){function f(){angular.isFunction(c)&&(d=c,c={}),this.exclusions={},this.inclusions={},this.serializeMappings={},this.deserializeMappings={},this.customSerializedAttributes={},this.preservedAttributes={},this.customSerializers={},this.nestedResources={},this.options=angular.extend({excludeByDefault:!1},b,c||{}),d&&d.call(this,this)}return f.prototype.exclude=function(){var a=this.exclusions;return angular.forEach(arguments,function(b){a[b]=!1}),this},f.prototype.only=function(){var a=this.inclusions;return this.options.excludeByDefault=!0,angular.forEach(arguments,function(b){a[b]=!0}),this},f.prototype.nestedAttribute=function(){var a=this;return angular.forEach(arguments,function(b){a.rename(b,b+"_attributes")}),this},f.prototype.resource=function(a,b,c){return this.nestedResources[a]=b,c&&this.serializeWith(a,c),this},f.prototype.rename=function(b,c,d){return this.serializeMappings[b]=c,(d||d===a)&&(this.deserializeMappings[c]=b),this},f.prototype.add=function(a,b){return this.customSerializedAttributes[a]=b,this},f.prototype.preserve=function(a){return this.preservedAttributes[a]=!0,this},f.prototype.serializeWith=function(a,b){return this.customSerializers[a]=b,this},f.prototype.isExcludedFromSerialization=function(b){if(this.options.excludeByDefault&&!this.inclusions.hasOwnProperty(b)||this.exclusions.hasOwnProperty(b))return!0;if(this.options.exclusionMatchers){var c=!1;return angular.forEach(this.options.exclusionMatchers,function(d){angular.isString(d)?c=c||0===b.indexOf(d):angular.isFunction(d)?c=c||d.call(a,b):d instanceof RegExp&&(c=c||d.test(b))}),c}return!1},f.prototype.getSerializedAttributeName=function(b){var c=this.serializeMappings[b]||b;return this.isExcludedFromSerialization(b)||this.isExcludedFromSerialization(c)?a:this.underscore(c)},f.prototype.isExcludedFromDeserialization=function(){return!1},f.prototype.getDeserializedAttributeName=function(b){var c=this.camelize(b);return c=this.deserializeMappings[b]||this.deserializeMappings[c]||c,this.isExcludedFromDeserialization(b)||this.isExcludedFromDeserialization(c)?a:c},f.prototype.getNestedResource=function(a){return e.getDependency(this.nestedResources[a])},f.prototype.getAttributeSerializer=function(b){var c=this.getNestedResource(b),d=this.customSerializers[b];return d?e.createService(d):c?c.config.serializer:a},f.prototype.serializeValue=function(a){var b=a,c=this;if(angular.isArray(a))b=[],angular.forEach(a,function(a){b.push(c.serializeValue(a))});else if(angular.isObject(a)){if(angular.isDate(a))return a;b={},angular.forEach(a,function(a,d){angular.isFunction(a)||c.serializeAttribute(b,d,a)})}return b},f.prototype.serializeAttribute=function(b,c,d){var e=this.getAttributeSerializer(c),f=this.getSerializedAttributeName(c);f!==a&&(b[f]=e?e.serialize(d):this.serializeValue(d))},f.prototype.serialize=function(a){var b=this.serializeValue(a),c=this;return angular.isObject(b)&&angular.forEach(this.customSerializedAttributes,function(d,e){angular.isFunction(d)&&(d=d.call(a,a)),c.serializeAttribute(b,e,d)}),b},f.prototype.deserializeValue=function(a,b){var c=a,d=this;if(angular.isArray(a))c=[],angular.forEach(a,function(a){c.push(d.deserializeValue(a,b))});else if(angular.isObject(a)){if(angular.isDate(a))return a;c={},b&&(c=new b.config.resourceConstructor),angular.forEach(a,function(a,b){d.deserializeAttribute(c,b,a)})}return c},f.prototype.deserializeAttribute=function(b,c,d){var e,f,g=this.getDeserializedAttributeName(c);g!==a&&(e=this.getAttributeSerializer(g),f=this.getNestedResource(g),b[g]=this.preservedAttributes[g]?d:e?e.deserialize(d,f):this.deserializeValue(d,f))},f.prototype.deserialize=function(a,b){return this.deserializeValue(a,b)},f.prototype.pluralize=function(a){return this.options.pluralize?this.options.pluralize(a):a},f.prototype.underscore=function(a){return this.options.underscore?this.options.underscore(a):a},f.prototype.camelize=function(a){return this.options.camelize?this.options.camelize(a):a},f}return b.underscore=b.underscore||d.underscore,b.camelize=b.camelize||d.camelize,b.pluralize=b.pluralize||d.pluralize,f.defaultOptions=b,f}]})}(),function(a){angular.module("rails").factory("railsRootWrappingTransformer",function(){return function(a,b){var c={};return c[angular.isArray(a)?b.config.pluralName:b.config.name]=a,c}}),angular.module("rails").factory("railsRootWrappingInterceptor",function(){return function(a){var b=a.resource;return b?a.then(function(a){return a.data&&a.data.hasOwnProperty(b.config.name)?a.data=a.data[b.config.name]:a.data&&a.data.hasOwnProperty(b.config.pluralName)&&(a.data=a.data[b.config.pluralName]),a}):a}}),angular.module("rails").provider("RailsResource",function(){var b={rootWrapping:!0,updateMethod:"put",httpConfig:{},defaultParams:a};this.rootWrapping=function(a){return b.rootWrapping=a,this},this.updateMethod=function(a){return b.updateMethod=a,this},this.httpConfig=function(a){return b.httpConfig=a,this},this.defaultParams=function(a){return b.defaultParams=a,this},this.$get=["$http","$q","railsUrlBuilder","railsSerializer","railsRootWrappingTransformer","railsRootWrappingInterceptor","RailsResourceInjector",function(c,d,e,f,g,h,i){function j(a,b){return b&&("/"!==b[0]&&(a+="/"),a+=b),a}function k(a,b){for(var c,d=0,e=a.length;e>d;d++)c=a[d],angular.isString(c)&&(c=a[d]=i.getDependency(c)),b(c)}function l(a){var b=this;if(a){var c=function(a){return{resource:l,context:b,response:a,then:function(a){return this.response=a(this.response,this.resource,this.context),c(this.response)}}},d=this.constructor.callInterceptors(c({data:a}),this).response.data;angular.extend(this,d)}}return l.extend=function(a){function b(){this.constructor=a}var c={}.hasOwnProperty,d=this;for(var e in d)c.call(d,e)&&(a[e]=d[e]);return b.prototype=d.prototype,a.prototype=new b,a.__super__=d.prototype,a},l.configure=function(c){c=c||{},this.config&&(c=angular.extend({},this.config,c)),this.config={},this.config.url=c.url,this.config.rootWrapping=c.rootWrapping===a?b.rootWrapping:c.rootWrapping,this.config.httpConfig=c.httpConfig||b.httpConfig,this.config.httpConfig.headers=angular.extend({Accept:"application/json","Content-Type":"application/json"},this.config.httpConfig.headers||{}),this.config.defaultParams=c.defaultParams||b.defaultParams,this.config.updateMethod=(c.updateMethod||b.updateMethod).toLowerCase(),this.config.requestTransformers=c.requestTransformers?c.requestTransformers.slice(0):[],this.config.responseInterceptors=c.responseInterceptors?c.responseInterceptors.slice(0):[],this.config.afterResponseInterceptors=c.afterResponseInterceptors?c.afterResponseInterceptors.slice(0):[],this.config.serializer=angular.isObject(c.serializer)?c.serializer:i.createService(c.serializer||f()),this.config.name=this.config.serializer.underscore(c.name),this.config.pluralName=this.config.serializer.underscore(c.pluralName||this.config.serializer.pluralize(this.config.name)),this.config.urlBuilder=e(this.config.url),this.config.resourceConstructor=this},l.configure({}),l.setUrl=function(a){this.configure({url:a})},l.buildUrl=function(a){return this.config.urlBuilder(a)},l.beforeResponse=function(a){a=i.getDependency(a),this.config.responseInterceptors.push(function(b){return b.then(function(c){return a(c.data,b.resource.config.resourceConstructor,b.context),c})})},l.afterResponse=function(a){a=i.getDependency(a),this.config.afterResponseInterceptors.push(function(b){return b.then(function(c){return a(c,b.resource.config.resourceConstructor),c})})},l.beforeRequest=function(a){a=i.getDependency(a),this.config.requestTransformers.push(function(b,c){return a(b,c.config.resourceConstructor)||b})},l.transformData=function(a){var b=this.config;return a=b.serializer.serialize(a),k(this.config.requestTransformers,function(c){a=c(a,b.resourceConstructor)}),b.rootWrapping&&(a=g(a,b.resourceConstructor)),a},l.callInterceptors=function(a,b){var c=this.config;return a=a.then(function(a){return a.originalData=a.data,a}),c.rootWrapping&&(a.resource=c.resourceConstructor,a=h(a)),a.then(function(a){return a.data=c.serializer.deserialize(a.data,c.resourceConstructor),a}),k(c.responseInterceptors,function(d){a.resource=c.resourceConstructor,a.context=b,a=d(a)}),a},l.callAfterInterceptors=function(a){var b=this.config;return k(b.afterResponseInterceptors,function(c){a.resource=b.resourceConstructor,a=c(a)}),a},l.processResponse=function(a){return a=this.callInterceptors(a).then(function(a){return a.data}),this.callAfterInterceptors(a)},l.getParameters=function(a){var b;return this.config.defaultParams&&(b=this.config.defaultParams),angular.isObject(a)&&(b=angular.extend(b||{},a)),b},l.getHttpConfig=function(a){var b=this.getParameters(a);return b?angular.extend({params:b},this.config.httpConfig):angular.copy(this.config.httpConfig)},l.$url=l.resourceUrl=function(a,b){return angular.isObject(a)||(a={id:a}),j(this.buildUrl(a||{}),b)},l.$get=function(a,b){return this.processResponse(c.get(a,this.getHttpConfig(b)))},l.query=function(a,b){return this.$get(this.resourceUrl(b),a)},l.get=function(a,b){return this.$get(this.resourceUrl(a),b)},l.prototype.$url=function(a){return j(this.constructor.resourceUrl(this),a)},l.prototype.processResponse=function(a){return a=this.constructor.callInterceptors(a,this),a=a.then(angular.bind(this,function(a){return a.hasOwnProperty("data")&&angular.isObject(a.data)&&angular.extend(this,a.data),this})),this.constructor.callAfterInterceptors(a)},angular.forEach(["post","put","patch"],function(a){l["$"+a]=function(b,d){var e;return d=this.transformData(angular.copy(d,{})),e=angular.extend({method:a,url:b,data:d},this.getHttpConfig()),this.processResponse(c(e))},l.prototype["$"+a]=function(b){var d,e;return d=this.constructor.transformData(angular.copy(this,{})),e=angular.extend({method:a,url:b,data:d},this.constructor.getHttpConfig()),this.processResponse(c(e))}}),l.prototype.create=function(){return this.$post(this.$url(),this)},l.prototype.update=function(){return this["$"+this.constructor.config.updateMethod](this.$url(),this)},l.prototype.isNew=function(){return null==this.id},l.prototype.save=function(){return this.isNew()?this.create():this.update()},l.$delete=function(a){return this.processResponse(c["delete"](a,this.getHttpConfig()))},l.prototype.$delete=function(a){return this.processResponse(c["delete"](a,this.constructor.getHttpConfig()))},l.prototype.remove=l.prototype["delete"]=function(){return this.$delete(this.$url())},l}]}),angular.module("rails").factory("railsResourceFactory",["RailsResource",function(a){return function(b){function c(){c.__super__.constructor.apply(this,arguments)}return a.extend(c),c.configure(b),c}}])}();
|
7
|
+
!function(){angular.module("rails",["ng"])}(),function(){angular.module("rails").factory("RailsInflector",function(){function a(a){return angular.isString(a)?a.replace(/_[\w\d]/g,function(a,b,c){return 0===b?a:c.charAt(b+1).toUpperCase()}):a}function b(a){return angular.isString(a)?a.replace(/[A-Z]/g,function(a,b){return 0===b?a:"_"+a.toLowerCase()}):a}function c(a){return a+"s"}return{camelize:a,underscore:b,pluralize:c}})}(),function(a){angular.module("rails").factory("RailsResourceInjector",["$injector",function(b){function c(c){return c?angular.isString(c)?b.get(c):c:a}function d(d){return d?b.instantiate(c(d)):a}return{createService:d,getDependency:c}}])}(),function(){angular.module("rails").factory("railsUrlBuilder",["$interpolate",function(a){return function(b){var c;return angular.isFunction(b)||angular.isUndefined(b)?b:(-1===b.indexOf(a.startSymbol())&&(b=b+"/"+a.startSymbol()+"id"+a.endSymbol()),c=a(b),function(a){return b=c(a),"/"===b.charAt(b.length-1)&&(b=b.substr(0,b.length-1)),b})}}])}(),function(a){angular.module("rails").provider("railsSerializer",function(){var b={underscore:a,camelize:a,pluralize:a,exclusionMatchers:[]};this.underscore=function(a){return b.underscore=a,this},this.camelize=function(a){return b.camelize=a,this},this.pluralize=function(a){return b.pluralize=a,this},this.exclusionMatchers=function(a){return b.exclusionMatchers=a,this},this.$get=["$injector","RailsInflector","RailsResourceInjector",function(c,d,e){function f(c,d){function f(){angular.isFunction(c)&&(d=c,c={}),this.exclusions={},this.inclusions={},this.serializeMappings={},this.deserializeMappings={},this.customSerializedAttributes={},this.preservedAttributes={},this.customSerializers={},this.nestedResources={},this.options=angular.extend({excludeByDefault:!1},b,c||{}),d&&d.call(this,this)}return f.prototype.exclude=function(){var a=this.exclusions;return angular.forEach(arguments,function(b){a[b]=!1}),this},f.prototype.only=function(){var a=this.inclusions;return this.options.excludeByDefault=!0,angular.forEach(arguments,function(b){a[b]=!0}),this},f.prototype.nestedAttribute=function(){var a=this;return angular.forEach(arguments,function(b){a.rename(b,b+"_attributes")}),this},f.prototype.resource=function(a,b,c){return this.nestedResources[a]=b,c&&this.serializeWith(a,c),this},f.prototype.rename=function(b,c,d){return this.serializeMappings[b]=c,(d||d===a)&&(this.deserializeMappings[c]=b),this},f.prototype.add=function(a,b){return this.customSerializedAttributes[a]=b,this},f.prototype.preserve=function(a){return this.preservedAttributes[a]=!0,this},f.prototype.serializeWith=function(a,b){return this.customSerializers[a]=b,this},f.prototype.isExcludedFromSerialization=function(b){if(this.options.excludeByDefault&&!this.inclusions.hasOwnProperty(b)||this.exclusions.hasOwnProperty(b))return!0;if(this.options.exclusionMatchers){var c=!1;return angular.forEach(this.options.exclusionMatchers,function(d){angular.isString(d)?c=c||0===b.indexOf(d):angular.isFunction(d)?c=c||d.call(a,b):d instanceof RegExp&&(c=c||d.test(b))}),c}return!1},f.prototype.getSerializedAttributeName=function(b){var c=this.serializeMappings[b]||b,d=this.isExcludedFromSerialization(c),e=this.isExcludedFromSerialization(b);if(this.options.excludeByDefault){if(d&&e)return a}else if(d||e)return a;return this.underscore(c)},f.prototype.isExcludedFromDeserialization=function(){return!1},f.prototype.getDeserializedAttributeName=function(b){var c=this.camelize(b);return c=this.deserializeMappings[b]||this.deserializeMappings[c]||c,this.isExcludedFromDeserialization(b)||this.isExcludedFromDeserialization(c)?a:c},f.prototype.getNestedResource=function(a){return e.getDependency(this.nestedResources[a])},f.prototype.getAttributeSerializer=function(b){var c=this.getNestedResource(b),d=this.customSerializers[b];return d?e.createService(d):c?c.config.serializer:a},f.prototype.serializeValue=function(a){var b=a,c=this;if(angular.isArray(a))b=[],angular.forEach(a,function(a){b.push(c.serializeValue(a))});else if(angular.isObject(a)){if(angular.isDate(a))return a;b={},angular.forEach(a,function(a,d){angular.isFunction(a)||c.serializeAttribute(b,d,a)})}return b},f.prototype.serializeAttribute=function(b,c,d){var e=this.getAttributeSerializer(c),f=this.getSerializedAttributeName(c);f!==a&&(b[f]=e?e.serialize(d):this.serializeValue(d))},f.prototype.serialize=function(a){var b=this.serializeValue(a),c=this;return angular.isObject(b)&&angular.forEach(this.customSerializedAttributes,function(d,e){angular.isFunction(d)&&(d=d.call(a,a)),c.serializeAttribute(b,e,d)}),b},f.prototype.deserializeValue=function(a,b){var c=a,d=this;if(angular.isArray(a))c=[],angular.forEach(a,function(a){c.push(d.deserializeValue(a,b))});else if(angular.isObject(a)){if(angular.isDate(a))return a;c={},b&&(c=new b.config.resourceConstructor),angular.forEach(a,function(a,b){d.deserializeAttribute(c,b,a)})}return c},f.prototype.deserializeAttribute=function(b,c,d){var e,f,g=this.getDeserializedAttributeName(c);g!==a&&(e=this.getAttributeSerializer(g),f=this.getNestedResource(g),b[g]=this.preservedAttributes[g]?d:e?e.deserialize(d,f):this.deserializeValue(d,f))},f.prototype.deserialize=function(a,b){return this.deserializeValue(a,b)},f.prototype.pluralize=function(a){return this.options.pluralize?this.options.pluralize(a):a},f.prototype.underscore=function(a){return this.options.underscore?this.options.underscore(a):a},f.prototype.camelize=function(a){return this.options.camelize?this.options.camelize(a):a},f}return b.underscore=b.underscore||d.underscore,b.camelize=b.camelize||d.camelize,b.pluralize=b.pluralize||d.pluralize,f.defaultOptions=b,f}]})}(),function(a){angular.module("rails").factory("railsRootWrappingTransformer",function(){return function(a,b){var c={};return c[angular.isArray(a)?b.config.pluralName:b.config.name]=a,c}}),angular.module("rails").factory("railsRootWrappingInterceptor",function(){return function(a){var b=a.resource;return b?a.then(function(a){return a.data&&a.data.hasOwnProperty(b.config.name)?a.data=a.data[b.config.name]:a.data&&a.data.hasOwnProperty(b.config.pluralName)&&(a.data=a.data[b.config.pluralName]),a}):a}}),angular.module("rails").provider("RailsResource",function(){var b={rootWrapping:!0,updateMethod:"put",httpConfig:{},defaultParams:a};this.rootWrapping=function(a){return b.rootWrapping=a,this},this.updateMethod=function(a){return b.updateMethod=a,this},this.httpConfig=function(a){return b.httpConfig=a,this},this.defaultParams=function(a){return b.defaultParams=a,this},this.$get=["$http","$q","railsUrlBuilder","railsSerializer","railsRootWrappingTransformer","railsRootWrappingInterceptor","RailsResourceInjector",function(c,d,e,f,g,h,i){function j(a,b){return b&&("/"!==b[0]&&(a+="/"),a+=b),a}function k(a,b){for(var c,d=0,e=a.length;e>d;d++)c=a[d],angular.isString(c)&&(c=a[d]=i.getDependency(c)),b(c)}function l(a){var b=this;if(a){var c=function(a){return{resource:l,context:b,response:a,then:function(a){return this.response=a(this.response,this.resource,this.context),c(this.response)}}},d=this.constructor.callInterceptors(c({data:a}),this).response.data;angular.extend(this,d)}}return l.extend=function(a){function b(){this.constructor=a}var c={}.hasOwnProperty,d=this;for(var e in d)c.call(d,e)&&(a[e]=d[e]);return b.prototype=d.prototype,a.prototype=new b,a.__super__=d.prototype,a},l.configure=function(c){c=c||{},this.config&&(c=angular.extend({},this.config,c)),this.config={},this.config.url=c.url,this.config.rootWrapping=c.rootWrapping===a?b.rootWrapping:c.rootWrapping,this.config.httpConfig=c.httpConfig||b.httpConfig,this.config.httpConfig.headers=angular.extend({Accept:"application/json","Content-Type":"application/json"},this.config.httpConfig.headers||{}),this.config.defaultParams=c.defaultParams||b.defaultParams,this.config.updateMethod=(c.updateMethod||b.updateMethod).toLowerCase(),this.config.requestTransformers=c.requestTransformers?c.requestTransformers.slice(0):[],this.config.responseInterceptors=c.responseInterceptors?c.responseInterceptors.slice(0):[],this.config.afterResponseInterceptors=c.afterResponseInterceptors?c.afterResponseInterceptors.slice(0):[],this.config.serializer=angular.isObject(c.serializer)?c.serializer:i.createService(c.serializer||f()),this.config.name=this.config.serializer.underscore(c.name),this.config.name&&(this.config.pluralName=this.config.serializer.underscore(c.pluralName||this.config.serializer.pluralize(this.config.name))),this.config.urlBuilder=e(this.config.url),this.config.resourceConstructor=this},l.configure({}),l.setUrl=function(a){this.configure({url:a})},l.buildUrl=function(a){return this.config.urlBuilder(a)},l.beforeResponse=function(a){a=i.getDependency(a),this.config.responseInterceptors.push(function(b){return b.then(function(c){return a(c.data,b.resource.config.resourceConstructor,b.context),c})})},l.afterResponse=function(a){a=i.getDependency(a),this.config.afterResponseInterceptors.push(function(b){return b.then(function(c){return a(c,b.resource.config.resourceConstructor),c})})},l.beforeRequest=function(a){a=i.getDependency(a),this.config.requestTransformers.push(function(b,c){return a(b,c.config.resourceConstructor)||b})},l.transformData=function(a){var b=this.config;return a=b.serializer.serialize(a),k(this.config.requestTransformers,function(c){a=c(a,b.resourceConstructor)}),b.rootWrapping&&(a=g(a,b.resourceConstructor)),a},l.callInterceptors=function(a,b){var c=this.config;return a=a.then(function(a){return a.originalData=a.data,a}),c.rootWrapping&&(a.resource=c.resourceConstructor,a=h(a)),a.then(function(a){return a.data=c.serializer.deserialize(a.data,c.resourceConstructor),a}),k(c.responseInterceptors,function(d){a.resource=c.resourceConstructor,a.context=b,a=d(a)}),a},l.callAfterInterceptors=function(a){var b=this.config;return k(b.afterResponseInterceptors,function(c){a.resource=b.resourceConstructor,a=c(a)}),a},l.processResponse=function(a){return a=this.callInterceptors(a).then(function(a){return a.data}),this.callAfterInterceptors(a)},l.getParameters=function(a){var b;return this.config.defaultParams&&(b=this.config.defaultParams),angular.isObject(a)&&(b=angular.extend(b||{},a)),b},l.getHttpConfig=function(a){var b=this.getParameters(a);return b?angular.extend({params:b},this.config.httpConfig):angular.copy(this.config.httpConfig)},l.$url=l.resourceUrl=function(a,b){return angular.isObject(a)||(a={id:a}),j(this.buildUrl(a||{}),b)},l.$get=function(a,b){return this.processResponse(c.get(a,this.getHttpConfig(b)))},l.query=function(a,b){return this.$get(this.resourceUrl(b),a)},l.get=function(a,b){return this.$get(this.resourceUrl(a),b)},l.prototype.$url=function(a){return j(this.constructor.resourceUrl(this),a)},l.prototype.processResponse=function(a){return a=this.constructor.callInterceptors(a,this),a=a.then(angular.bind(this,function(a){return a.hasOwnProperty("data")&&angular.isObject(a.data)&&angular.extend(this,a.data),this})),this.constructor.callAfterInterceptors(a)},angular.forEach(["post","put","patch"],function(a){l["$"+a]=function(b,d){var e;return d=this.transformData(angular.copy(d)),e=angular.extend({method:a,url:b,data:d},this.getHttpConfig()),this.processResponse(c(e))},l.prototype["$"+a]=function(b){var d,e;return d=this.constructor.transformData(angular.copy(this,{})),e=angular.extend({method:a,url:b,data:d},this.constructor.getHttpConfig()),this.processResponse(c(e))}}),l.prototype.create=function(){return this.$post(this.$url(),this)},l.prototype.update=function(){return this["$"+this.constructor.config.updateMethod](this.$url(),this)},l.prototype.isNew=function(){return null==this.id},l.prototype.save=function(){return this.isNew()?this.create():this.update()},l.$delete=function(a){return this.processResponse(c["delete"](a,this.getHttpConfig()))},l.prototype.$delete=function(a){return this.processResponse(c["delete"](a,this.constructor.getHttpConfig()))},l.prototype.remove=l.prototype["delete"]=function(){return this.$delete(this.$url())},l}]}),angular.module("rails").factory("railsResourceFactory",["RailsResource",function(a){return function(b){function c(){c.__super__.constructor.apply(this,arguments)}return a.extend(c),c.configure(b),c}}])}();
|
Binary file
|
data/bower.json
CHANGED
data/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "angularjs-rails-resource",
|
3
3
|
"description" : "A resource factory inspired by $resource from AngularJS",
|
4
|
-
"version": "1.0.0-
|
4
|
+
"version": "1.0.0-pre.2",
|
5
5
|
"main" : "dist/angularjs-rails-resource.min.js",
|
6
6
|
"homepage" : "https://github.com/FineLinePrototyping/angularjs-rails-resource.git",
|
7
7
|
"author" : "",
|
@@ -426,6 +426,14 @@ describe('railsResourceFactory', function () {
|
|
426
426
|
expect(test).toEqualData({id: 123, abc: 'xyz', xyz: 'abc', extra: 'test'});
|
427
427
|
}));
|
428
428
|
});
|
429
|
+
|
430
|
+
it('should be able to $post an array of resources', function () {
|
431
|
+
var data = [{id: 123, abc: 'xyz'}, {id: 124, abc: 'xyz'}];
|
432
|
+
$httpBackend['expectPOST']('/xyz', {tests: data} ).respond(200, {tests: data});
|
433
|
+
Test.$post('/xyz', data);
|
434
|
+
$httpBackend.flush();
|
435
|
+
});
|
436
|
+
|
429
437
|
});
|
430
438
|
|
431
439
|
describe('plural', function() {
|
@@ -390,6 +390,22 @@ describe('railsSerializer', function () {
|
|
390
390
|
result = serializer.deserialize({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
391
391
|
expect(result).toEqualData({id: 1, first: 'George', middle: 'R. R.', last: 'Martin'});
|
392
392
|
});
|
393
|
+
|
394
|
+
it('should only serialize id and books', function() {
|
395
|
+
var result,
|
396
|
+
serializer = createSerializer(function(config) {
|
397
|
+
this.only('id', 'books');
|
398
|
+
this.nestedAttribute('books');
|
399
|
+
this.serializeWith('books', factory(function() { }));
|
400
|
+
});
|
401
|
+
var book = { id: 1, title: 'A Game of Thrones', publicationDate: '1996-08-06' };
|
402
|
+
result = serializer.serialize({
|
403
|
+
id: 1, first: 'George', last: 'Martin', books: [book]
|
404
|
+
});
|
405
|
+
expect(result).toEqualData({ id: 1, books_attributes: [{ id: 1, title: 'A Game of Thrones', publication_date: '1996-08-06' }] });
|
406
|
+
result = serializer.deserialize(result);
|
407
|
+
expect(result).toEqual({ id: 1, books: [book]});
|
408
|
+
});
|
393
409
|
});
|
394
410
|
});
|
395
411
|
});
|
@@ -149,7 +149,11 @@
|
|
149
149
|
}
|
150
150
|
|
151
151
|
this.config.name = this.config.serializer.underscore(cfg.name);
|
152
|
-
|
152
|
+
|
153
|
+
// we don't want to turn undefined name into "undefineds" then the plural name won't update when the name is set
|
154
|
+
if (this.config.name) {
|
155
|
+
this.config.pluralName = this.config.serializer.underscore(cfg.pluralName || this.config.serializer.pluralize(this.config.name));
|
156
|
+
}
|
153
157
|
|
154
158
|
this.config.urlBuilder = railsUrlBuilder(this.config.url);
|
155
159
|
this.config.resourceConstructor = this;
|
@@ -360,7 +364,7 @@
|
|
360
364
|
RailsResource['$' + method] = function (url, data) {
|
361
365
|
var config;
|
362
366
|
// clone so we can manipulate w/o modifying the actual instance
|
363
|
-
data = this.transformData(angular.copy(data
|
367
|
+
data = this.transformData(angular.copy(data));
|
364
368
|
config = angular.extend({method: method, url: url, data: data}, this.getHttpConfig());
|
365
369
|
return this.processResponse($http(config));
|
366
370
|
};
|
@@ -263,8 +263,17 @@
|
|
263
263
|
Serializer.prototype.getSerializedAttributeName = function (attributeName) {
|
264
264
|
var mappedName = this.serializeMappings[attributeName] || attributeName;
|
265
265
|
|
266
|
-
|
267
|
-
|
266
|
+
var mappedNameExcluded = this.isExcludedFromSerialization(mappedName),
|
267
|
+
attributeNameExcluded = this.isExcludedFromSerialization(attributeName);
|
268
|
+
|
269
|
+
if(this.options.excludeByDefault) {
|
270
|
+
if(mappedNameExcluded && attributeNameExcluded) {
|
271
|
+
return undefined;
|
272
|
+
}
|
273
|
+
} else {
|
274
|
+
if (mappedNameExcluded || attributeNameExcluded) {
|
275
|
+
return undefined;
|
276
|
+
}
|
268
277
|
}
|
269
278
|
|
270
279
|
return this.underscore(mappedName);
|
@@ -329,7 +338,7 @@
|
|
329
338
|
|
330
339
|
// custom serializer takes precedence over resource serializer
|
331
340
|
if (serializer) {
|
332
|
-
return RailsResourceInjector.createService(serializer)
|
341
|
+
return RailsResourceInjector.createService(serializer);
|
333
342
|
} else if (resource) {
|
334
343
|
return resource.config.serializer;
|
335
344
|
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: angularjs-rails-resource
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.
|
4
|
+
version: 1.0.0.pre.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tommy Odom
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-11-24 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A small AngularJS add-on for integrating with Rails via JSON more easily.
|
15
15
|
email:
|