angularjs-rails-resource 1.0.0.pre.1 → 1.0.0.pre.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/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:
|