angularjs-rails-resource 1.0.0.pre.2 → 1.0.0.pre.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e088a0ef4c31ca6952015c7e5bf25e29a3aeffa6
4
- data.tar.gz: ceafd0fc62d19853922b36a79b3926cd1ca579c9
3
+ metadata.gz: f7ce09b68d048977e8091b90cd120e0f7836f183
4
+ data.tar.gz: 2c0eb42c1684eb64a5fd58e80a7adc8fed7e4e2f
5
5
  SHA512:
6
- metadata.gz: 8715afd2c22e4a5341512ba1845d83c6b5044cb6592dec4574fe530f908866ad9a48cc9f51b1fcfefe977bd30cf8661e5e39f2240c61ed9a0237be1cb81a6e28
7
- data.tar.gz: 93efebbbb2920fe2f2d6deb883bdfbe18cb8e5a720e93c946471deb1b9e8d6794820421e1dd4589179fc9643fb2c0eed90261458dbea030f05b291deda8f894c
6
+ metadata.gz: 6eb139ae046e2756eba924f354fbc386d752994ce43bbb67f5696f5c8567cc5ac49a125c7b687079c4766bce508dbd67dbc9c86097647e502daaf00952b01677
7
+ data.tar.gz: 56415e2fc32de4a5bd82db9cf0ece3ab680aa583bbb61a5df39bd2f8d14c95a2e74b3028c877da15f6fe648a86f6977937d1be9188d3971a4437d0ba295d3bf3
data/.gitignore CHANGED
@@ -18,4 +18,5 @@ tmp
18
18
  test_out
19
19
  atlassian-ide-plugin.xml
20
20
  node_modules
21
+ build/
21
22
 
data/CHANGELOG.md CHANGED
@@ -3,7 +3,9 @@
3
3
  ## Bug Fixes
4
4
 
5
5
  ## Features
6
- - Added <code>configure</code> to allow changing configuration options after the resource has been initially configured.
6
+ - Added <code>configure</code> function to allow changing configuration options after the resource has been initially configured.
7
+ - Separated out RailsResource into separate service to allow subclassing without using the factories.
8
+ - Added snapshot and rollback extension, be sure to check the [README](README.md#serializers) for details.
7
9
 
8
10
  ## Breaking Changes
9
11
  - <code>railsResourceFactoryProvider</code> settings have been moved to <code>RailsResourceProvider</code>
@@ -13,6 +15,60 @@
13
15
  - <code>enableRootWrapping</code> was renamed <code>rootWrapping</code>
14
16
  - <code>rootName</code> was renamed <code>name</code>
15
17
  - <code>rootPluralName</code> was renamed <code>pluralName</code>
18
+ - Query parameters were not underscored previously. We are now underscoring parameters by default.
19
+ The configuration option <code>underscoreParams</code> can be set to false to disable the renaming.
20
+
21
+ <a name="1.0.0-pre.3"></a>
22
+ # 1.0.0-pre.3
23
+ ## Features
24
+ - Added mixin capability, see [README](README.md#mixins) for details
25
+ - Added snapshot and rollback extension, see [README](README.md#serializers) for details.
26
+ - Added <code>underscoreParams</code> configuration option to allow turning off parameter underscore renaming.
27
+
28
+ ## Breaking Changes
29
+ - Query parameters were not underscored previously. We are now underscoring parameters by default.
30
+ The configuration option <code>underscoreParams</code> can be set to false to disable the renaming.
31
+
32
+ <a name="1.0.0-pre.2"></a>
33
+ # 1.0.0-pre.2
34
+ ## Bug Fixes
35
+ - Support submitting array data (#85)
36
+
37
+ <a name="1.0.0-pre.1"></a>
38
+ # 1.0.0-pre.1
39
+ ## Bug Fixes
40
+
41
+ ## Features
42
+ - Added <code>configure</code> function to allow changing configuration options after the resource has been initially configured.
43
+ - Separated out RailsResource into separate service to allow subclassing without using the factories.
44
+
45
+ ## Breaking Changes
46
+ - <code>railsResourceFactoryProvider</code> settings have been moved to <code>RailsResourceProvider</code>
47
+ - <code>wrapData</code> config option has been renamed <code>rootWrapping</code>
48
+ - All resource settings are now stored under the <code>config</code> property on the resource and should be modified using the <code>configure</code> function.
49
+ - The following resource settings have been renamed:
50
+ - <code>enableRootWrapping</code> was renamed <code>rootWrapping</code>
51
+ - <code>rootName</code> was renamed <code>name</code>
52
+ - <code>rootPluralName</code> was renamed <code>pluralName</code>
53
+ - Query parameters were not underscored previously. We are now underscoring parameters by default.
54
+ The configuration option <code>underscoreParams</code> can be set to false to disable the renaming.
55
+ - Replaced <code>railsRootWrappingTransformer</code> and <code>railsRootWrappingInterceptor</code> with <code>railsRootWrapper</code>
56
+ that has wrap & unwrap methods. This eliminates the need for using promises during resource construction to handle unwrapping
57
+ data passed into the constructor.
58
+ - Resource constructor no longer executes response interceptors. If you need to customize the constructor you should look
59
+ at using subclassing instead.
60
+ - <code>processResponse</code>, <code>transformData</code>, <code>callInterceptors</code> have all been removed as part of rewriting
61
+ the request / response handling.
62
+
63
+ <a name="0.2.5"></a>
64
+ # 0.2.5
65
+ ## Bug Fixes
66
+ - Support submitting array data (#85)
67
+
68
+ <a name="0.2.4"></a>
69
+ # 0.2.4
70
+ ## Bug Fixes
71
+ - Fix mapped name behavior when using serializer default exclusion (#81)
16
72
 
17
73
  <a name="0.2.3"></a>
18
74
  # 0.2.3
data/Gruntfile.js CHANGED
@@ -1,14 +1,17 @@
1
1
  module.exports = function(grunt) {
2
-
3
2
  var path = require('path');
4
3
 
5
4
  var srcFolder = 'vendor/assets/javascripts/angularjs/rails/resource/',
6
5
  srcFiles = ["index.js", "utils/**/*.js", "serialization.js", "resource.js"].map(function(glob) {
7
6
  return srcFolder + glob;
7
+ }),
8
+ extensionFiles = ["extensions/**/*.js"].map(function(glob) {
9
+ return srcFolder + glob;
8
10
  });
9
11
 
10
12
  grunt.initConfig({
11
13
  pkg: grunt.file.readJSON('package.json'),
14
+
12
15
  meta: {
13
16
  banner: '/**\n' +
14
17
  ' * <%= pkg.description %>\n' +
@@ -17,9 +20,21 @@ module.exports = function(grunt) {
17
20
  ' * @author <%= pkg.author %>\n' +
18
21
  ' */\n'
19
22
  },
23
+
20
24
  dirs: {
21
- dest: './'
25
+ dest: 'build'
26
+ },
27
+
28
+ clean: ['<%= dirs.dest %>'],
29
+
30
+ copy: {
31
+ extensions: {
32
+ files: [
33
+ {expand: true, flatten: true, src: extensionFiles, dest: '<%= dirs.dest %>/extensions'}
34
+ ]
35
+ }
22
36
  },
37
+
23
38
  concat: {
24
39
  options: {
25
40
  banner: "<%= meta.banner %>"
@@ -30,25 +45,35 @@ module.exports = function(grunt) {
30
45
  options: {
31
46
  process: function(src, filepath) {
32
47
  return src.replace(/^\/\/= require.*\n/gm, '');
33
- },
34
- },
48
+ }
49
+ }
35
50
  }
36
51
  },
37
- zip: {
38
- '<%= dirs.dest %>/angularjs-rails-resource.zip': ['<%= dirs.dest %>/<%= pkg.name %>.js', '<%= dirs.dest %>/<%= pkg.name %>.min.js']
52
+
53
+ compress: {
54
+ dist: {
55
+ options: {
56
+ archive: '<%= dirs.dest %>/angularjs-rails-resource.zip'
57
+ },
58
+ files: [
59
+ {expand: true, cwd: '<%= dirs.dest %>', src: ['**/*.js']}
60
+ ]
61
+ }
39
62
  },
63
+
40
64
  uglify: {
41
65
  options: {
42
66
  banner: "<%= meta.banner %>"
43
67
  },
44
68
  dist: {
45
- files: {
46
- '<%= dirs.dest %>/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
47
- }
69
+ files: [
70
+ {expand: true, cwd: '<%= dirs.dest %>', src: ['**/*.js'], dest: '<%= dirs.dest %>', ext: '.min.js'}
71
+ ]
48
72
  }
49
73
  },
74
+
50
75
  jshint: {
51
- files: ['gruntfile.js'],
76
+ files: ['gruntfile.js'].concat(srcFiles),
52
77
  options: {
53
78
  // options here to override JSHint defaults
54
79
  globals: {
@@ -56,9 +81,19 @@ module.exports = function(grunt) {
56
81
  }
57
82
  }
58
83
  },
84
+
59
85
  watch: {
60
86
  files: ['<%= jshint.files %>'],
61
- tasks: ['jshint', 'qunit']
87
+ tasks: ['jshint']
88
+ },
89
+
90
+ bump: {
91
+ options: {
92
+ files: ['package.json', 'bower.json'],
93
+ commit: false,
94
+ createTag: false,
95
+ push: false
96
+ }
62
97
  }
63
98
  });
64
99
 
@@ -66,30 +101,10 @@ module.exports = function(grunt) {
66
101
  grunt.loadNpmTasks('grunt-contrib-jshint');
67
102
  grunt.loadNpmTasks('grunt-contrib-watch');
68
103
  grunt.loadNpmTasks('grunt-contrib-concat');
69
- grunt.loadNpmTasks('grunt-zip');
70
-
71
- grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'zip']);
72
-
73
- // Provides the "bump" task.
74
- grunt.registerTask('bump', 'Increment version number', function() {
75
- var versionType = grunt.option('type');
76
- function bumpVersion(version, versionType) {
77
- var type = {patch: 2, minor: 1, major: 0},
78
- parts = version.split('.'),
79
- idx = type[versionType || 'patch'];
80
- parts[idx] = parseInt(parts[idx], 10) + 1;
81
- while(++idx < parts.length) { parts[idx] = 0; }
82
- return parts.join('.');
83
- }
84
- var version;
85
- function updateFile(file) {
86
- var json = grunt.file.readJSON(file);
87
- version = json.version = bumpVersion(json.version, versionType || 'patch');
88
- grunt.file.write(file, JSON.stringify(json, null, ' '));
89
- }
90
- updateFile('package.json');
91
- updateFile('bower.json');
92
- grunt.log.ok('Version bumped to ' + version);
93
- });
104
+ grunt.loadNpmTasks('grunt-contrib-copy');
105
+ grunt.loadNpmTasks('grunt-contrib-clean');
106
+ grunt.loadNpmTasks('grunt-contrib-compress');
107
+ grunt.loadNpmTasks('grunt-bump');
94
108
 
109
+ grunt.registerTask('default', ['jshint', 'clean', 'concat', 'copy', 'uglify', 'compress']);
95
110
  };
data/README.md CHANGED
@@ -26,18 +26,13 @@ Book.query({title: 'Moby Dick'}).then(function (books) {
26
26
  You can inject the <code>railsSerializerProvider</code> into your application config function and override the <code>underscore</code>
27
27
  and <code>camelize</code> functions:
28
28
  ````javascript
29
- angular.module('app').config(function (railsSerializerFactory) {
30
- railsSerializerProvider.
31
- underscore(function (name) {
32
- return name;
33
- }).
34
- camelize(function (name) {
35
- return name;
36
- });
37
- });
29
+ angular.module('app').config(["railsSerializerProvider", function(railsSerializerProvider) {
30
+ railsSerializerProvider.underscore(angular.identity).camelize(angular.identity);
31
+ }]);
38
32
  ````
39
33
 
40
34
  ## Installation
35
+ ### Rails Asset Pipeline
41
36
  Add this line to your application's Gemfile to use the latest stable version:
42
37
  ```ruby
43
38
  gem 'angularjs-rails-resource', '~> 0.2.3'
@@ -47,6 +42,19 @@ Include the javascript somewhere in your asset pipeline:
47
42
  ```javascript
48
43
  //= require angularjs/rails/resource
49
44
  ```
45
+
46
+ To add extensions just add additional requires:
47
+ ```javascript
48
+ //= require angularjs/rails/resource/extensions/snapshots
49
+ ```
50
+
51
+ ### Standalone
52
+ If you aren't using the Rails asset pipeline you can download the combined
53
+ [angularjs-rails-resource.js](https://github.com/FineLinePrototyping/dist-angularjs-rails-resource/blob/master/angularjs-rails-resource.js)
54
+ or [angularjs-rails-resource.min.js](https://github.com/FineLinePrototyping/dist-angularjs-rails-resource/blob/master/angularjs-rails-resource.min.js).
55
+
56
+ You can also use [Bower](http://bower.io/) to install <code>angularjs-rails-resource</code>.
57
+
50
58
  ## Branching and Versioning
51
59
  As much as possible we will try to adhere to the [SemVer](http://semver.org/) guidelines on release numbering.
52
60
 
@@ -57,35 +65,71 @@ Release branches should remain stable but it is always best to rely on the ruby
57
65
  ## Changes
58
66
  Make sure to check the [CHANGELOG](CHANGELOG.md) for any breaking changes between releases.
59
67
 
60
- ## Dependencies
61
- Since this is an [AngularJS](http://angularjs.org) module it of course depends on that but more specifically the it depends on the following AngularJS services:
62
-
63
- * [$http](http://docs.angularjs.org/api/ng.$http)
64
- * [$q](http://docs.angularjs.org/api/ng.$q)
65
- * [$injector](http://docs.angularjs.org/api/AUTO.$injector)
66
- * [$interpolate](http://docs.angularjs.org/api/ng.$interpolate)
67
-
68
68
  ## Usage
69
- There are a lot of different ways that you can use the resources and we try not to force you into any specific pattern
69
+ There are a lot of different ways that you can use the resources and we try not to force you into any specific pattern.
70
+ All of the functionality is packed in an AngularJS module named "rails" so make sure that your modules depend on that module
71
+ for the dependency injection to work properly.
70
72
 
71
73
  There are more examples available in [EXAMPLES.md](EXAMPLES.md).
72
74
 
75
+ ### Defining Resources
76
+ There are multiple ways that you can set up define new resources in your application.
77
+
78
+ #### railsResourceFactory
79
+ Similar to $resource, we provide a <code>railsResourceFactory(config)</code> function that takes a config object with the configuration
80
+ settings for the new resource. The factory function returns a new class that is extended from RailsResource.
73
81
 
74
- ### Basic Example
75
- In order to create a Book resource, we would first define the factory within a module.
76
82
  ```javascript
77
83
  angular.module('book.services', ['rails']);
78
84
  angular.module('book.services').factory('Book', ['railsResourceFactory', function (railsResourceFactory) {
79
- return railsResourceFactory({url: '/books', name: 'book'});
85
+ return railsResourceFactory({
86
+ url: '/books',
87
+ name: 'book'
88
+ });
80
89
  }]);
81
90
  ```
82
- We would then inject that service into a controller:
91
+
92
+ #### RailsResource extension
93
+ We also expose the RailsResource as base class that you can extend to create your own resource classes. Extending the RailsResource class
94
+ directly gives you a bit more flexibility to add custom constructor code. There are probably ten different ways to extend the class but
95
+ the two that we intend to be used are through CoffeeScript or through the same logic that the factory function uses.
96
+
97
+ ##### CoffeeScript
98
+ To allow better integration with CoffeeScript, we expose the RailsResource as a base class that can be extended to create
99
+ resource classes. When extending RailsResource you should use the <code>@configure</code> function to set configuration
100
+ properties for the resource. You can call <code>@configure</code> multiple times to set additional properties as well.
101
+
102
+ ````coffeescript
103
+ class Book extends RailsResource
104
+ @configure url: '/books', name: 'book'
105
+
106
+ class Encyclopedia extends Book
107
+ @configure url: '/encyclopedias', name: 'encyclopedia'
108
+ ````
109
+
110
+ ##### JavaScript
111
+ Since the purpose of exposing the RailsResource was to allow for CoffeeScript users to create classes from it the JavaScript way
112
+ is basically just the same as the generated CoffeeScript code. The <code>RailsResource.extendTo</code> function is a modification
113
+ of the <code>__extends</code> function that CoffeeScript generates.
114
+
115
+ ````javascript
116
+ function Resource() {
117
+ Resource.__super__.constructor.apply(this, arguments);
118
+ }
119
+
120
+ RailsResource.extendTo(Resource);
121
+ Resource.configure(config);
122
+ ````
123
+
124
+ ### Using Resources
83
125
  ```javascript
84
126
  angular.module('book.controllers').controller('BookShelfCtrl', ['$scope', 'Book', function ($scope, Book) {
85
127
  $scope.searching = true;
86
128
  // Find all books matching the title
87
- $scope.books = Book.query({title: title});
88
- $scope.books.then(function(results) {
129
+ $scope.books = Book.query({
130
+ title: title
131
+ });
132
+ $scope.books.then(function (results) {
89
133
  $scope.searching = false;
90
134
  }, function (error) {
91
135
  $scope.searching = false;
@@ -98,12 +142,17 @@ angular.module('book.controllers').controller('BookShelfCtrl', ['$scope', 'Book'
98
142
  });
99
143
 
100
144
  // Create a book and save it
101
- new Book({title: 'Gardens of the Moon', author: 'Steven Erikson', isbn: '0-553-81957-7'}).create();
145
+ new Book({
146
+ title: 'Gardens of the Moon',
147
+ author: 'Steven Erikson',
148
+ isbn: '0-553-81957-7'
149
+ }).create();
102
150
  }]);
103
151
  ```
104
152
 
105
- ### Serializer
106
- When defining a resource, you can pass a custom [serializer](#serializers) using the <code>serializer</code> configuration option.
153
+ ### Custom Serialization
154
+ When defining a resource, you can pass a custom [serializer](#serializers) using the <code>serializer</code> configuration option to
155
+ alter the behavior of the object serialization.
107
156
  ```javascript
108
157
  Author = railsResourceFactory({
109
158
  url: '/authors',
@@ -117,7 +166,7 @@ Author = railsResourceFactory({
117
166
  ```
118
167
  You can also specify a serializer as a factory and inject it as a dependency.
119
168
  ```javascript
120
- angular.module('rails').factory('BookSerializer', function(railsSerializer) {
169
+ angular.module('rails').factory('BookSerializer', function (railsSerializer) {
121
170
  return railsSerializer(function () {
122
171
  this.exclude('publicationDate', 'relatedBooks');
123
172
  this.rename('ISBN', 'isbn');
@@ -134,47 +183,14 @@ Book = railsResourceFactory({
134
183
  name: 'book',
135
184
  serializer: 'BookSerializer'
136
185
  });
137
-
138
186
  ```
139
- ## Resource Creation
140
- There are multiple ways that you can set up new resources in your application.
141
-
142
- ### railsResourceFactory
143
- Similar to $resource, we provide a <code>railsResourceFactory(config)</code> function that takes a config object with the configuration
144
- settings for the new resource. The factory function returns a new class that is extended from RailsResource.
145
-
146
- ### RailsResource extension
147
- We also expose the RailsResource as base class that you can extend to create your own resource classes. Extending the RailsResource class
148
- directly gives you a bit more flexibility to add custom constructor code. There are probably ten different ways to extend the class but
149
- the two that we intend to be used are through CoffeeScript or through the same logic that the factory function uses.
150
-
151
- #### CoffeeScript
152
- ````coffeescript
153
- class Book extends RailsResource
154
- @configure url: '/books', name: 'book'
155
187
 
156
- class Encyclopedia extends Book
157
- @configure url: '/encyclopedias', name: 'encyclopedia'
158
- ````
159
-
160
- #### JavaScript
161
- Since the purpose of exposing the RailsResource was to allow for CoffeeScript users to create classes from it the JavaScript way
162
- is basically just the same as the generated CoffeeScript code. The <code>RailsResource.extend</code> function is a modification
163
- of the <code>__extends</code> function that CoffeeScript generates.
164
-
165
- ````javascript
166
- function Resource() {
167
- Resource.__super__.constructor.apply(this, arguments);
168
- }
169
-
170
- RailsResource.extend(Resource);
171
- Resource.configure(config);
172
- ````
173
188
 
174
189
  ### Config Options
175
190
 
176
191
  The following configuration options are available for customizing resources. Each of the configuration options can be passed as part of an object
177
- to the <code>railsResourceFactory</code> function or to the resource's <code>configure</code> function.
192
+ to the <code>railsResourceFactory</code> function or to the resource's <code>configure</code> function. The <code>configure</code> function
193
+ defined on the resource can be called multiple times to adjust properties as needed.
178
194
 
179
195
  * **url** - This is the url of the service. See [Resource URLs](#resource-urls) below for more information.
180
196
  * **rootWrapping** - (Default: true) Turns on/off root wrapping on JSON (de)serialization.
@@ -186,8 +202,9 @@ to the <code>railsResourceFactory</code> function or to the resource's <code>con
186
202
  * **Accept** - application/json
187
203
  * **Content-Type** - application/json
188
204
  * **defaultParams** *(optional)* - If the resource expects a default set of query params on every call you can specify them here.
205
+ * **underscoreParams** *(optional)* - Controls whether or not query parameters are converted from camel case to underscore.
189
206
  * **updateMethod** *(optional)* - Allows overriding the default HTTP method (PUT) used for update. Valid values are "post", "put", or "patch".
190
- * **serializer** *(optional)* - Allows specifying a custom [serializer](#serializers) allow configuring custom serialization options.
207
+ * **serializer** *(optional)* - Allows specifying a custom [serializer](#serializers) to configure custom serialization options.
191
208
  * **requestTransformers** *(optional) - See [Transformers / Interceptors](#transformers--interceptors)
192
209
  * **responseInterceptors** *(optional)* - See [Transformers / Interceptors](#transformers--interceptors)
193
210
  * **afterResponseInterceptors** *(optional)* - See [Transformers / Interceptors](#transformers--interceptors)
@@ -200,10 +217,11 @@ For example, you should specify "publishingCompany" and "publishingCompanies" in
200
217
  The individual resource configuration takes precedence over application-wide default configuration values.
201
218
  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.
202
219
 
203
- * rootWrapping - {function(boolean):railsSerializerProvider}
204
- * httpConfig - {function(object):railsSerializerProvider}
205
- * defaultParams - {function(object):railsSerializerProvider}
206
- * updateMethod - {function(boolean):railsSerializerProvider}
220
+ * rootWrapping - {function(boolean):RailsResourceProvider}
221
+ * httpConfig - {function(object):RailsResourceProvider}
222
+ * defaultParams - {function(object):RailsResourceProvider}
223
+ * underscoreParams - {function(boolean):RailsResourceProvider}
224
+ * updateMethod - {function(boolean):RailsResourceProvider}
207
225
 
208
226
  For example, to turn off the root wrapping application-wide and set the update method to PATCH:
209
227
 
@@ -247,6 +265,10 @@ RailsResources have the following class methods available.
247
265
 
248
266
  * configure(options) - Change one or more configuration option for a resource.
249
267
 
268
+ * extendTo(child) - Modifies the child to be a subclass of a RailsResource. This can be used to create multiple levels of inheritance. See [RailsResource extension](#RailsResource-extension) for more information
269
+
270
+ * include(...module) - Includes a mixin module into the resource. See [Mixins](#mixins) for more information
271
+
250
272
  * setUrl(url) - Updates the url for the resource, same as calling <code>configure({url: url})</code>
251
273
 
252
274
  * $url(context, path) - Returns the resource URL using the given context with the optional path appended if provided.
@@ -441,6 +463,119 @@ The resource also exposes a class method <code>afterResponse(fn)</code> that acc
441
463
  to the list of after response interceptors for the resource class. Functions added with <code>afterResponse</code> don't need to know anything about promises since they are automatically wrapped
442
464
  as an interceptor.
443
465
 
466
+ ## Mixins
467
+ The ability to add a [Mixin](http://en.wikipedia.org/wiki/Mixin) to a RailsResource is modeled after the example code in
468
+ in the [Classes](http://arcturo.github.io/library/coffeescript/03_classes.html) chapter of [The Little Book on CoffeeScript](http://arcturo.github.io/library/coffeescript/index.html).
469
+
470
+ RailsResource provides two methods:
471
+ * **extend** - Add class properties / methods to the resource
472
+ * **include** - Add instance properties / methods to the resource prototype chain
473
+
474
+ When you call <code>extend</code> or <code>include</code> the mixin will be added to the resource. If your mixin provides
475
+ one of the callback methods (<code>extended</code> or <code>included</code>) then those methods will be called when the mixin
476
+ is added. One additional change from the normal mixin behavior is that your mixins can implement an additional <code>configure</code>
477
+ function that will be called whenever the resource's <code>configure</code> function is called. That way the mixin can provide
478
+ additional configuration options.
479
+
480
+ ## Extensions
481
+ Extensions are provided [mixins](#mixins) that follow specific naming pattern to make it easier to include them by a shortened name.
482
+
483
+ The available extension names are:
484
+ * [snapshots](#snapshots) - RailsResourceSnapshotsMixin
485
+
486
+ To include an extension, you have to first include the extension in your project.
487
+ You then need to add the extension to the in one of the following ways to RailsResource:
488
+
489
+ ### Application-wide Resource Extensions
490
+ <code>RailsResourceProvider.extensions</code> - adds the extension to all RailsResources within the application.
491
+ ````javascript
492
+ app.config(function (RailsResourceProvider) {
493
+ RailsResourceProvider.extensions('snapshots');
494
+ });
495
+ ````
496
+
497
+ ### Per-Resource Extensions
498
+ #### Configuration Option
499
+ The <code>extensions</code> configuration option adds the extension to a single RailsResource
500
+
501
+ ##### JavaScript
502
+ ````javascript
503
+ Book = railsResourceFactory({
504
+ url: '/books',
505
+ name: 'book',
506
+ extensions: ['snapshots']
507
+ });
508
+ ````
509
+ ##### CoffeeScript
510
+ ````coffeescript
511
+ class Book extends RailsResource
512
+ @configure url: '/books', name: 'book', extensions: ['snapshots']
513
+ ````
514
+
515
+ #### RailsResource.extend
516
+ RailsResource.extend - explicitly include the extension as a module
517
+
518
+ ##### JavaScript
519
+ ````javascript
520
+ Book = railsResourceFactory({ url: '/books', name: 'book' });
521
+ // by name
522
+ Book.extend('RailsResourceSnapshotsMixin');
523
+ // or by injected reference
524
+ Book.extend(RailsResourceSnapshotsMixin);
525
+ ````
526
+
527
+ ##### CoffeeScript
528
+
529
+ ````coffeescript
530
+ class Book extends RailsResource
531
+ @configure url: '/books', name: 'book'
532
+ @extend 'RailsResourceSnapshotsMixin'
533
+ ````
534
+
535
+ ### Snapshots
536
+ Snapshots allow you to save off the state of the resource at a specific point in time and if need be roll back to one of the
537
+ saved snapshots and yes, you can create as many snapshots as you want.
538
+
539
+ Snapshots serialize the resource instance and save off a copy of the serialized data in the <code>$snapshots</code> array on the instance.
540
+ If you use a custom serialization options to control what is sent to the server you may want to consider whether or not you want to use
541
+ different serialization options. If so, you can specify an specific serializer for snapshots using the <code>snapshotSerializer</code> configuration
542
+ option.
543
+
544
+ Calling <code>save</code>, <code>create</code>, <code>update</code>, or <code>delete</code>/<code>remove</code> on a resource instance
545
+ will remove all snapshots when the operation completes successfully.
546
+
547
+ #### Configuration Options
548
+ * **snapshotSerializer** *(optional)* - Allows specifying a custom [serializer](#serializers) to configure custom serialization options specific to [snapshot and rollback](#snapshots).
549
+
550
+
551
+ #### Creating Snapshots
552
+ Creating a snapshot is easy, just call the <code>snapshot</code> function. You can pass an optional callback function to <code>snapshot</code> to perform
553
+ additional custom operations after the rollback is complete. The callback function is specific to each snapshot version created so make sure you pass it every
554
+ time if it's a callback you always want called.
555
+
556
+ #### Rolling back
557
+ So you want to undo changes to the resource? There are two methods you can use to roll back the resource to a previous snapshot version <code>rollback</code>
558
+ and <code>rollbackTo</code>. Each method will:
559
+ * Deserialize the snapshot data and update the resource instance with the new data.
560
+ * Remove all snapshots newer than the version being rolled back to.
561
+ * Call the rollback callback if it was specified on the <code>snapshot</code> in the context of the resource instance.
562
+
563
+ ##### rollback
564
+ <code>rollback(numVersions)</code> allows you to roll back the resource. If you do not specify <code>numVersions</code> then a resource is rolled back to the last
565
+ snapshot version. <code>numVersions</code> can be used to roll back further than the last snapshot version based on the following rules:
566
+
567
+ * When <code>numVersions</code> is undefined or 0 then a single version is rolled back.
568
+ * When <code>numVersions</code> exceeds the stored number of snapshots then the resource is rolled back to the first snapshot version.
569
+ * When <code>numVersions</code> is less than 0 then the resource is rolled back to the first snapshot version.
570
+ * Otherwise, <code>numVersions</code> represents the nth version from the last snapshot version (similar to calling rollback <code>numVersions</code> times).
571
+
572
+ ##### rollbackTo
573
+ <code>rollbackTo(snapshotVersion)</code> allows you to roll back the resource to a specific snapshot version.
574
+
575
+ * When <code>snapshotVersion</code> is greater than the number of versions then the last snapshot version will be used.
576
+ * When <code>snapshotVersion</code> is less than 0 then the resource will be rolled back to the first version.
577
+ * Otherwise, the resource will be rolled back to the specific version specified.
578
+
444
579
  ## Tests
445
580
  The tests are written using [Jasmine](http://pivotal.github.com/jasmine/) and are run using [Karma](https://github.com/karma-runner/karma).
446
581