diff --git a/.gitignore b/.gitignore
index 52cd695..2cf357e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
.DS_Store
coverage/
-node_modules/
\ No newline at end of file
+node_modules/
+build/
diff --git a/.jscsrc b/.jscsrc
index efc1d6e..9cd25e4 100644
--- a/.jscsrc
+++ b/.jscsrc
@@ -1,5 +1,14 @@
{
- "preset" : "google",
- "maximumLineLength" : 120,
- "disallowMultipleVarDecl" : false
+ "preset": "google",
+ "maximumLineLength": 120,
+ "disallowMultipleVarDecl": false,
+ "jsDoc": {
+ "checkAnnotations": {
+ "preset": "jsdoc3",
+ "extra": {
+ "ngdoc": "some",
+ "methodOf": "some"
+ }
+ }
+ }
}
diff --git a/Gulpfile.js b/Gulpfile.js
index 0b8c647..6edbb61 100644
--- a/Gulpfile.js
+++ b/Gulpfile.js
@@ -7,7 +7,7 @@ var jshint = require('gulp-jshint');
var jscs = require('gulp-jscs');
var nsp = require('gulp-nsp');
var runSequence = require('run-sequence');
-var istanbul = require('gulp-istanbul');
+var istanbul = require('gulp-istanbul');
/*
* PLEASE NOTE: run-sequence is a
@@ -21,6 +21,17 @@ var paths = {
'src': 'src/**/*.js'
};
+gulp.task('ngdocs', [], function () {
+ var gulpDocs = require('gulp-ngdocs');
+ return gulp.src(paths.src)
+ .pipe(gulpDocs.process({
+ html5Mode: false,
+ startPage: '/api',
+ title: 'angular-model'
+ }))
+ .pipe(gulp.dest('./build/docs'));
+});
+
gulp.task('test', function(done) {
new Server({
configFile: __dirname + '/config/karma.conf.js',
diff --git a/README.md b/README.md
index 8cdf84d..f087892 100644
--- a/README.md
+++ b/README.md
@@ -11,3 +11,301 @@
**Angular Model** is a module that provides a simple way to bind client-side domain logic to JSON-based API resources.
By sticking to hypermedia design principles, Angular Model allows you to implement client applications that are cleanly decoupled from your server architecture.
+
+## Basic Usage
+
+In your AngularJS application, include the JavaScript:
+
+```html
+// your specific paths may vary
+
+```
+
+In your app configuration, state a dependency on [Angular Model](https://github.com/radify/angular-model):
+
+```javascript
+angular.module('myApp', [
+ 'ur.model'
+]);
+```
+
+## API documentation
+
+The source code is documented using the ngdoc standard using [gulp-ngdocs](https://www.npmjs.com/package/gulp-ngdocs/). A markdown version is browseable at [/docs](/docs/api.md).
+
+To generate documentation in HTML, run:
+
+```bash
+gulp ngdocs
+```
+
+This will output docs into the `build/docs` directory. Then, using a server like `ws`, start a local web server:
+
+```bash
+cd build/docs
+npm install -g ws
+ws
+```
+
+Then, you should be able to browse to http://localhost:8000 to view the API documentation for angular-model.
+
+## Configuration
+
+Here is a quick reference guide to all the configuration settings you can pass to the model() constructor, which is [documented in full in the API documentation](/docs/api.md). Each one is then described in detail later in this document, and in full in the source code in the `src` directory.
+
+Setting | Type | Description
+------- | ---- | -----------
+url | string | API url that this model maps to
+defaults | object literal | Default values of attributes of instances of this model. Similar to properties in OOP.
+$instance | object literal | Instance methods available on each instance of this model.
+$class | object literal | Class methods available on this model. Similar to static methods in OOP.
+$collection | object literal | Collection
+
+### Defaults
+
+```javascript
+yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ /**
+ * @ngdoc object
+ * @name yourApp.posts.defaults
+ * @description
+ * Configure the default attributes for instances of posts.
+ *
+ * This is similar to an OOP class, which has attributes with defaults, e.g. "public string foo = 'bar';"
+ */
+ defaults: {
+ name: '', // The name of the post
+ published: false, // Whether the post has been released to the general public
+ body: '', // Body text of this post
+ logo: null, // The logo to show for this post
+ author: 'John Doe'// Who wrote the post?
+ }
+ });
+});
+```
+
+Here is an example of how the defaults get used:
+
+```javascript
+var post = model('posts').create({});
+console.log(post.author);
+=> John Doe
+```
+
+## Creating instances of your model
+
+You can use angular-model ad-hoc to construct object instances:
+
+```javascript
+// From defaults
+var post = model('posts').create({});
+
+// Specifying fields
+var post = model('posts').create({
+ name: 'some post',
+ body: "body of some body, it's just some body, you know?",
+ author: 'Steve Davis'
+});
+
+console.log(post.author);
+=> Steve Davis
+```
+
+## Instance Methods
+
+angular-model instances have instance methods, similar to objects in the OOP world.
+
+### Default instance methods
+
+The following methods are available to every angular-model instance.
+
+Function | Description
+------- | -----------
+$save | Persist an instance to the API
+$delete | Tell the API to delete an instance
+$reload | Refresh an instance of a model from the API
+$revert | Reset the model to the state it was originally in when you first got it from the API
+$exists | Checks whether an object exists in the API, based on whether it has an identity URL.
+$dirty | Returns boolean - true if a model instance has been modified, else false. Opposite of $pristine.
+$pristine | Returns boolean - true if a model instance has unmodified, else false. Opposite of $dirty.
+$related | Hydrates the $links property of the instance. $links are used so that an instance can tell the client which objects are related to it. For example, a `post` may have an `author` object related to it.
+$modified | Returns a map of the properties that have been changed
+$hasRelated | Does an instance have a relation of name `name`?
+
+> You can see full details of these methods in the [API documentation](/docs/api.md).
+
+### Custom instance methods
+
+angular-model allows you to define instance methods on instances. This is similar to adding methods by extending a base class in the OOP world.
+
+```javascript
+yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ // ...
+
+ /**
+ * @ngdoc object
+ * @name yourApp.posts.$instance
+ * @description
+ * Instance methods that are callable on any individual instance of a post
+ */
+ $instance: {
+ /**
+ * @ngdoc function
+ * @name yourApp.posts.$logo
+ * @description
+ * If this post instance has a logo, return it, otherwise return a default string
+ *
+ * @return string Either the logo for this post, or a default logo
+ */
+ $logo: function() {
+ return this.logo || '/logos/default.png';.
+ }
+ }
+ });
+});
+```
+
+Example:
+
+```javascript
+var post = model('Posts').create({
+ logo: 'foo.png'
+});
+console.log(post.$logo());
+=> foo.png
+```
+
+## Class methods
+
+### Default class methods
+
+The following methods are available statically to angular-model:
+
+Function | Description
+-------- | -----------
+all | Make a request to the API, based on the `url` configuration setting
+first | Given a query, get the first model instance from the API
+create | Create a new instance of the model. Defaults come from the `defaults` configuration setting.
+
+> You can see full details of these methods in the [API documentation](/docs/api.md).
+
+### Custom class methods
+
+angular-model allows you to define class methods on instances. This is similar to static methods in the OOP world.
+
+```javascript
+yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ // ...
+
+ /**
+ * @ngdoc object
+ * @name yourApp.posts.$class
+ * @description
+ * Class methods that are callable on the posts class, or any instance thereof. These
+ * behave similarly to static methods in OOP languages.
+ */
+ $class: {
+ /**
+ * @ngdoc function
+ * @name yourApp.posts.roles
+ * @description
+ * Get an array of valid post types.
+ *
+ * @return array The valid types that a post can have. Array of strings
+ */
+ types: function() {
+ return ['announcement', 'article']
+ }
+ }
+ });
+});
+```
+
+Example:
+
+```javascript
+console.log(model('Posts').types());
+=> ['announcement', 'article']
+```
+
+## Collection methods
+
+You can use collection methods as well, so you can deal with a bunch of instances together. This allows you to have powerful and expressive methods on collections.
+
+### Default collection methods
+
+The following methods are available statically to angular-model:
+
+Function | Description
+-------- | -----------
+add | Saves the `object` with `data`
+remove | Find `index` and delete it from the API, then remove it from the collection
+
+> You can see full details of these methods in the [API documentation](/docs/api.md).
+
+### Custom collection methods
+
+```javascript
+yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ // ...
+
+ /**
+ * @ngdoc object
+ * @name yourApp.posts.$collection
+ * @description
+ * Methods that apply to a collection of posts together
+ */
+ $collection: {
+ /**
+ * @ngdoc function
+ * @name yourApp.posts.$hasArchived
+ * @description
+ * Operates on a collection of posts and determines whether any of them are archived
+ *
+ * @requires _ Lodash library is used to search the collection
+ *
+ * @return string Either the logo for this post, or a default logo
+ */
+ $hasArchived: function() {
+ return !angular.isUndefined(_.find(this, { archived: true }));
+ }
+ }
+ });
+});
+```
+
+Example:
+
+```javascript
+model('Posts').all().then(function(posts) {
+ if (posts.$hasArchived()) {
+ // Some of the posts in the collection are archived
+ }
+});
+```
+
+Running unit tests
+--
+
+Install the test runner with npm:
+
+```bash
+npm install
+```
+
+You can then run the tests with gulp:
+
+```bash
+gulp
+```
+
+Tests can be found in the `spec` directory of this project.
+
+Related
+--
+
+You may wish to use [Angular Scaffold](https://github.com/radify/angular-scaffold/), which is is a collection of convenience wrappers around angular-model collections. Really helpful for building your AngularJS application with angular-model.
diff --git a/docs/api.md b/docs/api.md
new file mode 100644
index 0000000..73ad727
--- /dev/null
+++ b/docs/api.md
@@ -0,0 +1,907 @@
+# angular-model API documentation
+
+
+`model`
+=======
+
+function in module `ur`
+
+Description
+-----------
+
+Main factory function for angular-model
+
+Usage
+-----
+
+```javascript
+model(name[, options]);
+```
+
+#### Parameters
+
+
+
+#### Example
+
+ post.$delete();
+
+### $dirty()
+
+Returns boolean - true if a model instance is unmodified, else false. Inverse of $pristine.
+
+##### Returns
+
+
true if a model instance is modified, else false. Inverse of $pristine.
+
+
+
+
+
+#### Example
+
+ if (post.$pristine()) { console.log('It is just as it was when we got it from the API'); }
+
+### $exists()
+
+Checks whether an object exists in the API, based on whether it has an identity URL.
+
+##### Returns
+
+
True if the identifier of this instance exists in the API
+
+
+
+
+
+#### Example
+
+ if (post.$exists()) { console.log('It exists'); }
+
+### $hasRelated(name)
+
+Does an instance have a relation of name `name`?
+
+##### Parameters
+
+
+
+#### Example
+
+ if (post.$hasRelated('author')) { console.log('Post has an author'); }
+
+### $modified()
+
+Returns a map of the properties that have been changed
+
+##### Returns
+
+
Map of the fields that have been changed from the $pristine version
+
+
+
+
+
+#### Example
+
+ console.log(post.$modified());
+
+### $pristine()
+
+Returns boolean - false if a model instance is unmodified, else true. Inverse of $dirty.
+
+##### Returns
+
+
true if a model instance is unmodified, else false. Inverse of $dirty.
+
+
+
+
+
+#### Example
+
+ if (post.$dirty()) { console.log('Post has been modified'); }
+
+### $related()
+
+Hydrates the $links property of the instance. $links are used so that an instance can tell the client which objects are related to it. For example, a `post` may have an `author` object related to it.
+
+##### Returns
+
+
+
+#### Example
+
+ post.$reload();
+
+### $revert()
+
+Reset the model to the state it was originally in when you first got it from the API
+
+#### Example
+
+ post.$revert();
+
+### $save(data)
+
+Persist an instance to the API
+
+##### Parameters
+
+
+
+#### Example
+
+ var post = model('posts').create({ name: 'some post' });
+ post.$save();
+
+
+`$class`
+========
+
+object in module `ur`
+
+Description
+-----------
+
+Methods available on the model class
+
+Analogous to static methods in the OOP world
+
+You can specify custom class methods:
+
+ yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ $class: {
+ types: function() {
+ return ['announcement', 'article']
+ }
+ }
+ });
+ });
+
+Methods
+-------
+
+### all(data, headers)
+
+Retrieve collection of post instances from the API
+
+##### Parameters
+
+
+
+#### Example
+
+ model('posts').all().then(function(posts) {
+ console.log(posts.length);
+ });
+ => 4
+
+### create(data)
+
+Creates an instance on of the model
+
+##### Parameters
+
+
+
+
+`link`
+======
+
+directive in module `ur.model`
+
+Description
+-----------
+
+angular-model will scan your page looking for `` tags. It will use these to work out where your API endpoints are for your angular-model classes.
+
+So, if you have a "class" Posts, you would define a link with an href pointing to the API endpoint for Posts. This should be a HATEOS-compliant API endpoint.
+
+Dependencies
+------------
+
+`model`
+
+Usage
+-----
+
+as element:
+```javascript
+
+
+```
+
+#### Parameters
+
+
Where should angular-model look for the API for this resource.
+
+
+
+
+
+Example
+-------
+
+
+
+ My Posts Application
+
+
+
diff --git a/package.json b/package.json
index 24b3f9c..fad35b9 100644
--- a/package.json
+++ b/package.json
@@ -20,6 +20,16 @@
"name": "John Mercer",
"email": "john@radify.io",
"web": "http://radify.io"
+ },
+ {
+ "name": "Gavin Davies",
+ "email": "gavin@radify.io",
+ "web": "http://radify.io"
+ },
+ {
+ "name": "Warren Seymour",
+ "email": "warren@radify.io",
+ "web": "http://radify.io"
}
],
"repository": {
@@ -35,6 +45,7 @@
"gulp-istanbul": "^0.10.2",
"gulp-jscs": "^3.0.2",
"gulp-jshint": "^1.12.0",
+ "gulp-ngdocs": "^0.2.13",
"gulp-nsp": "^2.0.1",
"jasmine-core": "^2.3.4",
"karma": "^0.13.14",
diff --git a/src/angular-model.js b/src/angular-model.js
index bc36492..caab631 100644
--- a/src/angular-model.js
+++ b/src/angular-model.js
@@ -9,8 +9,7 @@
(function(window, angular, undefined) {
'use strict';
-var noop = angular.noop,
- forEach = angular.forEach,
+var forEach = angular.forEach,
extend = angular.extend,
copy = angular.copy,
isFunc = angular.isFunction,
@@ -79,6 +78,35 @@ function serialize(obj, prefix) {
return str.join('&');
}
+/**
+ * @ngdoc overview
+ * @name ur.model
+ * @requires angular
+ * @requires window
+ * @description
+ * Simple HATEOS-oriented persistence module for AngularJS.
+ *
+ * Angular Model is a module that provides a simple way to bind client-side domain logic to JSON-based API resources
+ *
+ * By sticking to hypermedia design principles, Angular Model allows you to implement client applications that are
+ * cleanly decoupled from your server architecture.
+ *
+ * angular-model allows you to perform CRUD against an API in a manner similar to Active Record.
+ *
+ * In your AngularJS application, include the JavaScript:
+ ```html
+ // your specific paths may vary
+
+ ```
+ *
+ * In your app configuration, state a dependency on Angular Model:
+
+ ```javascript
+ angular.module('myApp', [
+ 'ur.model'
+ ]);
+ ```
+ */
angular.module('ur.model', []).provider('model', function() {
var expr, // Used to evaluate expressions; initialized by the service invokation
@@ -138,11 +166,66 @@ angular.module('ur.model', []).provider('model', function() {
var DEFAULT_METHODS = {
- // Methods available on the model class
+ /**
+ * @ngdoc object
+ * @name ur.model:$class
+ * @description
+ * Methods available on the model class
+ *
+ * Analogous to static methods in the OOP world
+ *
+ * You can specify custom class methods:
+ *
+ yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ $class: {
+ types: function() {
+ return ['announcement', 'article']
+ }
+ }
+ });
+ });
+ */
$class: {
+ /**
+ * @ngdoc function
+ * @name all
+ * @methodOf ur.model:$class
+ * @param {object=} data Configuration of the request that will be sent to your API
+ * @param {object=} headers Map of custom headers to send to your API
+ *
+ * @description
+ * Retrieve collection of post instances from the API
+ * @example
+ ```
+ model('posts').all().then(function(posts) {
+ console.log(posts.length);
+ });
+ => 4
+ ```
+ * @returns {object} Promise from an API request
+ */
all: function(data, headers) {
return $request(null, this, 'GET', data, headers);
},
+
+ /**
+ * @ngdoc function
+ * @name first
+ * @methodOf ur.model:$class
+ * @param {object=} data Configuration of the request that will be sent to your API
+ *
+ * @description
+ * Retrieve a single post instances from the API
+ * @example
+ ```
+ model('posts').first({name: 'some post'}).then(function(post) {
+ console.log(post._id);
+ });
+ => 42
+ ```
+ * @returns {object} Promise from an API request
+ */
first: function(data) {
return this.all(data).then(function(response) {
return angular.isArray(response) ? response[0] : response;
@@ -150,13 +233,70 @@ angular.module('ur.model', []).provider('model', function() {
return null;
});
},
+
+ /**
+ * @ngdoc function
+ * @name create
+ * @methodOf ur.model:$class
+ * @param {object=} data Configuration of the instance that you are creating. Merged with any defaults
+ * specified when this model was declared.
+ *
+ * @description
+ * Creates an instance on of the model
+ *
+ * @example
+ ```
+ var post = model('Posts').create({});
+ ```
+ * @returns {object} angular-model instance
+ */
create: function(data) {
return this.instance(deepExtend(copy(this.$config().defaults), data || {}));
},
},
- // Methods available on model instances
+ /**
+ * @ngdoc object
+ * @name ur.model:$instance
+ * @description
+ * Methods available on model instances
+ *
+ * You can use these when you have created or loaded a model instance, see the example
+ *
+ var post = model('posts').first({_id: 42});
+ console.log(post.name);
+ => "Post with ID 42"
+
+ post.name = 'renamed';
+ post.$save();
+ *
+ * You can specify custom instance methods:
+ *
+ yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ $instance: {
+ $logo: function() {
+ return this.logo || '/logos/default.png';.
+ }
+ }
+ });
+ });
+ */
$instance: {
+ /**
+ * @ngdoc function
+ * @name $save
+ * @methodOf ur.model:$instance
+ * @description
+ * Persist an instance to the API
+ * @example
+ ```
+ var post = model('posts').create({ name: 'some post' });
+ post.$save();
+ ```
+ * @param {object=} data Data to save to this model instance. Defaults to the result of `this.$modified()`
+ * @returns {object} Promise from an API request
+ */
$save: function(data) {
var method, requestData;
@@ -174,12 +314,50 @@ angular.module('ur.model', []).provider('model', function() {
return $request(this, this.$model(), method, requestData);
},
+
+ /**
+ * @ngdoc function
+ * @name $delete
+ * @methodOf ur.model:$instance
+ * @description
+ * Delete an instance from the API
+ * @example
+ ```
+ post.$delete();
+ ```
+ * @returns {object} Promise from an API request
+ */
$delete: function() {
return $request(this, this.$model(), 'DELETE');
},
+
+ /**
+ * @ngdoc function
+ * @name $reload
+ * @methodOf ur.model:$instance
+ * @description
+ * Refresh an instance of a model from the API
+ * @example
+ ```
+ post.$reload();
+ ```
+ * @returns {object} Promise from an API request
+ */
$reload: function() {
return $request(this, this.$model(), 'GET');
},
+
+ /**
+ * @ngdoc function
+ * @name $revert
+ * @methodOf ur.model:$instance
+ * @description
+ * Reset the model to the state it was originally in when you first got it from the API
+ * @example
+ ```
+ post.$revert();
+ ```
+ */
$revert: function() {
var original = copy(this.$original());
@@ -191,15 +369,67 @@ angular.module('ur.model', []).provider('model', function() {
this[prop] = original[prop];
}
},
+
+ /**
+ * @ngdoc function
+ * @name $exists
+ * @methodOf ur.model:$instance
+ * @description
+ * Checks whether an object exists in the API, based on whether it has an identity URL.
+ * @example
+ ```
+ if (post.$exists()) { console.log('It exists'); }
+ ```
+ * @returns {boolean} True if the identifier of this instance exists in the API
+ */
$exists: function() {
return !!expr(this, this.$model().$config().identity).get();
},
+
+ /**
+ * @ngdoc function
+ * @name $dirty
+ * @methodOf ur.model:$instance
+ * @description
+ * Returns boolean - true if a model instance is unmodified, else false. Inverse of $pristine.
+ * @example
+ ```
+ if (post.$pristine()) { console.log('It is just as it was when we got it from the API'); }
+ ```
+ * @returns {boolean} true if a model instance is modified, else false. Inverse of $pristine.
+ */
$dirty: function() {
return !this.$pristine();
},
+
+ /**
+ * @ngdoc function
+ * @name $pristine
+ * @methodOf ur.model:$instance
+ * @description
+ * Returns boolean - false if a model instance is unmodified, else true. Inverse of $dirty.
+ * @example
+ ```
+ if (post.$dirty()) { console.log('Post has been modified'); }
+ ```
+ * @returns {boolean} true if a model instance is unmodified, else false. Inverse of $dirty.
+ */
$pristine: function() {
return equals(this, this.$original());
},
+
+ /**
+ * @ngdoc function
+ * @name $modified
+ * @methodOf ur.model:$instance
+ * @description
+ * Returns a map of the properties that have been changed
+ * @example
+ ```
+ console.log(post.$modified());
+ ```
+ * @returns {object} Map of the fields that have been changed from the $pristine version
+ */
$modified: function() {
var original = this.$original(), diff = {};
@@ -215,6 +445,21 @@ angular.module('ur.model', []).provider('model', function() {
return diff;
},
+
+ /**
+ * @ngdoc function
+ * @name $related
+ * @methodOf ur.model:$instance
+ * @description
+ * Hydrates the $links property of the instance. $links are used so that an instance
+ * can tell the client which objects are related to it. For example, a `post` may have an
+ * `author` object related to it.
+ * @example
+ ```
+ console.log(post.links());
+ ```
+ * @returns {object} Promise from the API
+ */
$related: function(name) {
var link, model, instance;
@@ -233,16 +478,71 @@ angular.module('ur.model', []).provider('model', function() {
return instance.$reload();
},
+
+ /**
+ * @ngdoc function
+ * @name $hasRelated
+ * @methodOf ur.model:$instance
+ * @param {string} name Name of the related property to check for
+ * @description
+ * Does an instance have a relation of name `name`?
+ * @example
+ ```
+ if (post.$hasRelated('author')) { console.log('Post has an author'); }
+ ```
+ * @returns {boolean} true if a $link to `name` exists on this instance
+ */
$hasRelated: function(name) {
return isObject(this.$links[name]);
}
},
- // Methods available on model collections
+ /**
+ * @ngdoc object
+ * @name ur.model:$collection
+ * @description
+ * Methods available on model collections
+ *
+ * You can use collection methods to deal with a bunch of instances together. This allows you to have powerful
+ * and expressive methods on collections.
+ *
+ * You can specify custom collection methods:
+ *
+ yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ $collection: {
+ $hasArchived: function() {
+ return !angular.isUndefined(_.find(this, { archived: true }));
+ }
+ },
+ });
+ });
+ */
$collection: {
+ /**
+ * @ngdoc function
+ * @name add
+ * @methodOf ur.model:$collection
+ * @param {object} object Object to persist data onto
+ * @param {object=} data Data to persist onto the object
+ * @description
+ * Saves the `object` with `data`
+ * @returns {boolean} true if a $link to `name` exists on this instance
+ */
add: function(object, data) {
return object.$save(data || {});
},
+
+ /**
+ * @ngdoc function
+ * @name remove
+ * @methodOf ur.model:$collection
+ * @param {(number|object)} index Either the index of the item in the collection to remove, or the object
+ * itself, which will be searched for in the collection
+ * @description
+ * Find `index` and delete it from the API, then remove it from the collection
+ * @returns {object} Promise from the API
+ */
remove: function(index) {
index = (typeof index !== 'number') ? index = this.indexOf(index) : index;
var self = this, result = self[index].$delete();
@@ -302,13 +602,50 @@ angular.module('ur.model', []).provider('model', function() {
}
extend(this, {
-
+ /**
+ * @ngdoc function
+ * @name ur.model:model
+ * @param {string} name Name of the 'class', e.g. 'posts'
+ * @param {object=} options Config to initialise the model 'class' with. You can supply an object literal to
+ * configure your model here.
+ * @description
+ * Main factory function for angular-model
+ *
+ * @example
+ ```
+ yourApp.config(function(modelProvider) {
+ modelProvider.model('posts', {
+ // configuration options
+ $instance: {
+ // custom instance functions
+ },
+ $class: {
+ // custom class functions
+ },
+ $collection: {
+ // custom collection functions
+ }
+ });
+ });
+ ```
+ * @returns {ur.model} instance of angular-model for the 'class' identified by 'name'
+ */
model: function(name, options) {
config(name, options);
return this;
},
- // Returns the model service
+ /**
+ * @ngdoc function
+ * @name ur.model:$get
+ * @description:
+ * Get the model class factory
+ *
+ * @param {object} $http https://docs.angularjs.org/api/ng/service/$http
+ * @param {object} $parse https://docs.angularjs.org/api/ng/service/$parse
+ * @param {object} $q https://docs.angularjs.org/api/ng/service/$q
+ * @return {object} The model service
+ */
$get: ['$http', '$parse', '$q', function($http, $parse, $q) {
q = $q;
http = $http;
@@ -383,8 +720,34 @@ angular.module('ur.model', []).provider('model', function() {
};
}
-}).directive('link', ['model', function(model) {
+})
+/**
+ * @ngdoc directive
+ * @name ur.model.directive:link
+ * @element link
+ * @restrict 'E'
+ * @param {string} rel Must be equal to "resource".
+ * @param {string} name The name of the angular-model "class" to use.
+ * @param {string} href Where should angular-model look for the API for this resource.
+ * @description
+ * angular-model will scan your page looking for `` tags. It will use these
+ * to work out where your API endpoints are for your angular-model classes.
+ *
+ * So, if you have a "class" Posts, you would define a link with an href pointing to the API endpoint
+ * for Posts. This should be a HATEOS-compliant API endpoint.
+ *
+ * @requires ur.model
+ *
+ * @example
+ ```html
+
+
+ My Posts Application
+
+ ```
+ */
+.directive('link', ['model', function(model) {
return {
restrict: 'E',
link: function(scope, element, attrs) {