diff --git a/docs.json b/docs.json
index 85ff8b591..de2066fe0 100644
--- a/docs.json
+++ b/docs.json
@@ -8,7 +8,11 @@
"docs/bundled-models.md",
"docs/cli.md",
"docs/types.md",
- "docs/api.md",
+ "docs/api-app.md",
+ "docs/api-datasource.md",
+ "docs/api-geopoint.md",
+ "docs/api-model.md",
+ "docs/api-model-remote.md",
"docs/ios.md",
"docs/js.md",
"docs/java.md",
diff --git a/docs/api-app.md b/docs/api-app.md
new file mode 100644
index 000000000..2115a21d1
--- /dev/null
+++ b/docs/api-app.md
@@ -0,0 +1,257 @@
+## App object
+
+The App object represents a Loopback application.
+
+The App object extends [Express](http://expressjs.com/api.html#express) and supports [Express / Connect middleware](http://expressjs.com/api.html#middleware). See [Express documentation](http://expressjs.com/api.html) for details.
+
+```js
+var loopback = require('loopback');
+var app = loopback();
+
+app.get('/', function(req, res){
+ res.send('hello world');
+});
+
+app.listen(3000);
+```
+
+## Properties
+
+### models
+
+The `app.models` object has properties for all defined models. In the following example the `Product` and `CustomerReceipt` models are accessed using the `models` object.
+
+**NOTE:** you must call `app.boot()` to create the `app.models` object.
+
+```js
+var loopback = require('loopback');
+var app = loopback();
+app.boot({
+ dataSources: {
+ db: {connector: 'memory'}
+ }
+});
+app.model('product', {dataSource: 'db'});
+app.model('customer-receipt', {dataSource: 'db'});
+
+// available based on the given name
+var Product = app.models.Product;
+
+// also available as camelCase
+var product = app.models.product;
+
+// multi-word models are avaiable as pascal cased
+var CustomerReceipt = app.models.CustomerReceipt;
+
+// also available as camelCase
+var customerReceipt = app.models.customerReceipt;
+```
+
+## Methods
+
+### app.boot([options])
+
+Initialize an application from an options object or a set of JSON and JavaScript files.
+
+**What happens during an app _boot_?**
+
+1. **DataSources** are created from an `options.dataSources` object or `datasources.json` in the current directory
+2. **Models** are created from an `options.models` object or `models.json` in the current directory
+3. Any JavaScript files in the `./models` directory are loaded with `require()`.
+
+**Options**
+
+ - `cwd` - _optional_ - the directory to use when loading JSON and JavaScript files
+ - `models` - _optional_ - an object containing `Model` definitions
+ - `dataSources` - _optional_ - an object containing `DataSource` definitions
+
+> **NOTE:** mixing `app.boot()` and `app.model(name, config)` in multiple files may result
+> in models being **undefined** due to race conditions. To avoid this when using `app.boot()`
+> make sure all models are passed as part of the `models` definition.
+
+
+**Model Definitions**
+
+The following is an example of an object containing two `Model` definitions: "location" and "inventory".
+
+```js
+{
+ "dealership": {
+ // a reference, by name, to a dataSource definition
+ "dataSource": "my-db",
+ // the options passed to Model.extend(name, properties, options)
+ "options": {
+ "relationships": {
+ "cars": {
+ "type": "hasMany",
+ "model": "Car",
+ "foreignKey": "dealerId"
+ }
+ },
+ "remoteMethods": {
+ "nearby": {
+ "description": "Find nearby locations around the geo point",
+ "accepts": [
+ {"arg": "here", "type": "GeoPoint", "required": true, "description": "geo location (lat & lng)"}
+ ],
+ "returns": {"arg": "locations", "root": true}
+ }
+ }
+ },
+ // the properties passed to Model.extend(name, properties, options)
+ "properties": {
+ "id": {"id": true},
+ "name": "String",
+ "zip": "Number",
+ "address": "String"
+ }
+ },
+ "car": {
+ "dataSource": "my-db"
+ "properties": {
+ "id": {
+ "type": "String",
+ "required": true,
+ "id": true
+ },
+ "make": {
+ "type": "String",
+ "required": true
+ },
+ "model": {
+ "type": "String",
+ "required": true
+ }
+ }
+ }
+}
+```
+
+**Model definition properties**
+
+ - `dataSource` - **required** - a string containing the name of the data source definition to attach the `Model` to
+ - `options` - _optional_ - an object containing `Model` options
+ - `properties` _optional_ - an object defining the `Model` properties in [LoopBack Definition Language](http://docs.strongloop.com/loopback-datasource-juggler/#loopback-definition-language)
+
+**DataSource definition properties**
+
+ - `connector` - **required** - the name of the [connector](#working-with-data-sources-and-connectors)
+
+### model(name, definition)
+
+Define a `Model` and export it for use by remote clients.
+
+**definition**
+
+- `public` - **default: true** attach the `Model` to the app and export its methods to clients
+- `dataSource` - **required** the name of the `DataSource` to attach the `Model` to
+
+Example:
+
+```js
+// declare a DataSource
+app.boot({
+ dataSources: {
+ db: {
+ connector: 'mongodb',
+ url: 'mongodb://localhost:27015/my-database-name'
+ }
+ }
+});
+
+// describe a model
+var modelDefinition = {dataSource: 'db'};
+
+// create the model
+var Product = app.model('product', modelDefinition);
+
+// use the model api
+Product.create({name: 'pencil', price: 0.99}, console.log);
+```
+
+**Note** - This will expose all [shared methods](#shared-methods) on the model.
+
+You may also export an existing `Model` by calling `app.model(Model)` like the example below.
+
+### models()
+
+Get the app's exported models. Only models defined using `app.model()` will show up in this list.
+
+```js
+var models = app.models();
+
+models.forEach(function (Model) {
+ console.log(Model.modelName); // color
+});
+```
+
+### docs(options)
+
+Enable swagger REST API documentation.
+
+**Options**
+
+ - `basePath` The basepath for your API - eg. 'http://localhost:3000'.
+
+**Example**
+
+```js
+// enable docs
+app.docs({basePath: 'http://localhost:3000'});
+```
+
+Run your app then navigate to [the API explorer](http://petstore.swagger.wordnik.com/). Enter your API basepath to view your generated docs.
+
+### app.use( router )
+
+Expose models over specified router.
+For example, to expose models over REST using the `loopback.rest` router:
+
+```js
+app.use(loopback.rest());
+```
+
+View generated REST documentation at [http://localhost:3000/_docs](http://localhost:3000/_docs).
+
+### Middleware
+
+LoopBack includes middleware similar to [Express / Connect middleware](http://expressjs.com/api.html#middleware).
+
+
+
+#### loopback.token(options)
+
+**Options**
+
+ - `cookies` - An `Array` of cookie names
+ - `headers` - An `Array` of header names
+ - `params` - An `Array` of param names
+
+Each array is used to add additional keys to find an `accessToken` for a `request`.
+
+The following example illustrates how to check for an `accessToken` in a custom cookie, query string parameter
+and header called `foo-auth`.
+
+```js
+app.use(loopback.token({
+ cookies: ['foo-auth'],
+ headers: ['foo-auth', 'X-Foo-Auth'],
+ cookies: ['foo-auth', 'foo_auth']
+}));
+```
+
+**Defaults**
+
+By default the following names will be checked. These names are appended to any optional names. They will always
+be checked, but any names specified will be checked first.
+
+```js
+ params.push('access_token');
+ headers.push('X-Access-Token');
+ headers.push('authorization');
+ cookies.push('access_token');
+ cookies.push('authorization');
+```
+
+> **NOTE:** The `loopback.token()` middleware will only check for [signed cookies](http://expressjs.com/api.html#req.signedCookies).
+
diff --git a/docs/api-datasource.md b/docs/api-datasource.md
new file mode 100644
index 000000000..69e8dc627
--- /dev/null
+++ b/docs/api-datasource.md
@@ -0,0 +1,194 @@
+## Data Source object
+
+A Loopback `DataSource` provides [Models](#model) with the ability to manipulate data. Attaching a `DataSource` to a `Model` adds [instance methods](#instance-methods) and [static methods](#static-methods) to the `Model`. The added methods may be [remote methods](#remote-methods).
+
+Define a data source for persisting models.
+
+```js
+var oracle = loopback.createDataSource({
+ connector: 'oracle',
+ host: '111.22.333.44',
+ database: 'MYDB',
+ username: 'username',
+ password: 'password'
+});
+```
+
+## Methods
+
+### dataSource.createModel(name, properties, options)
+
+Define a model and attach it to a `DataSource`.
+
+```js
+var Color = oracle.createModel('color', {name: String});
+```
+
+### dataSource.discoverModelDefinitions([username], fn)
+
+Discover a set of model definitions (table or collection names) based on tables or collections in a data source.
+
+```js
+oracle.discoverModelDefinitions(function (err, models) {
+ models.forEach(function (def) {
+ // def.name ~ the model name
+ oracle.discoverSchema(null, def.name, function (err, schema) {
+ console.log(schema);
+ });
+ });
+});
+```
+
+### dataSource.discoverSchema([owner], name, fn)
+
+Discover the schema of a specific table or collection.
+
+**Example schema from oracle connector:**
+
+```js
+ {
+ "name": "Product",
+ "options": {
+ "idInjection": false,
+ "oracle": {
+ "schema": "BLACKPOOL",
+ "table": "PRODUCT"
+ }
+ },
+ "properties": {
+ "id": {
+ "type": "String",
+ "required": true,
+ "length": 20,
+ "id": 1,
+ "oracle": {
+ "columnName": "ID",
+ "dataType": "VARCHAR2",
+ "dataLength": 20,
+ "nullable": "N"
+ }
+ },
+ "name": {
+ "type": "String",
+ "required": false,
+ "length": 64,
+ "oracle": {
+ "columnName": "NAME",
+ "dataType": "VARCHAR2",
+ "dataLength": 64,
+ "nullable": "Y"
+ }
+ },
+ "audibleRange": {
+ "type": "Number",
+ "required": false,
+ "length": 22,
+ "oracle": {
+ "columnName": "AUDIBLE_RANGE",
+ "dataType": "NUMBER",
+ "dataLength": 22,
+ "nullable": "Y"
+ }
+ },
+ "effectiveRange": {
+ "type": "Number",
+ "required": false,
+ "length": 22,
+ "oracle": {
+ "columnName": "EFFECTIVE_RANGE",
+ "dataType": "NUMBER",
+ "dataLength": 22,
+ "nullable": "Y"
+ }
+ },
+ "rounds": {
+ "type": "Number",
+ "required": false,
+ "length": 22,
+ "oracle": {
+ "columnName": "ROUNDS",
+ "dataType": "NUMBER",
+ "dataLength": 22,
+ "nullable": "Y"
+ }
+ },
+ "extras": {
+ "type": "String",
+ "required": false,
+ "length": 64,
+ "oracle": {
+ "columnName": "EXTRAS",
+ "dataType": "VARCHAR2",
+ "dataLength": 64,
+ "nullable": "Y"
+ }
+ },
+ "fireModes": {
+ "type": "String",
+ "required": false,
+ "length": 64,
+ "oracle": {
+ "columnName": "FIRE_MODES",
+ "dataType": "VARCHAR2",
+ "dataLength": 64,
+ "nullable": "Y"
+ }
+ }
+ }
+ }
+```
+
+### dataSource.enableRemote(operation)
+
+Enable remote access to a data source operation. Each [connector](#connector) has its own set of set remotely enabled and disabled operations. You can always list these by calling `dataSource.operations()`.
+
+
+### dataSource.disableRemote(operation)
+
+Disable remote access to a data source operation. Each [connector](#connector) has its own set of set enabled and disabled operations. You can always list these by calling `dataSource.operations()`.
+
+```js
+// all rest data source operations are
+// disabled by default
+var oracle = loopback.createDataSource({
+ connector: require('loopback-connector-oracle'),
+ host: '...',
+ ...
+});
+
+// or only disable it as a remote method
+oracle.disableRemote('destroyAll');
+```
+
+**Notes:**
+
+ - disabled operations will not be added to attached models
+ - disabling the remoting for a method only affects client access (it will still be available from server models)
+ - data sources must enable / disable operations before attaching or creating models
+
+### dataSource.operations()
+
+List the enabled and disabled operations.
+
+ console.log(oracle.operations());
+
+Output:
+
+```js
+{
+ find: {
+ remoteEnabled: true,
+ accepts: [...],
+ returns: [...]
+ enabled: true
+ },
+ save: {
+ remoteEnabled: true,
+ prototype: true,
+ accepts: [...],
+ returns: [...],
+ enabled: true
+ },
+ ...
+}
+```
diff --git a/docs/api-geopoint.md b/docs/api-geopoint.md
new file mode 100644
index 000000000..91db42e89
--- /dev/null
+++ b/docs/api-geopoint.md
@@ -0,0 +1,71 @@
+## GeoPoint object
+
+The GeoPoint object represents a physical location.
+
+Use the `GeoPoint` class.
+
+```js
+var GeoPoint = require('loopback').GeoPoint;
+```
+
+Embed a latitude / longitude point in a [Model](#model).
+
+```js
+var CoffeeShop = loopback.createModel('coffee-shop', {
+ location: 'GeoPoint'
+});
+```
+
+Loopback models with a GeoPoint property and an attached Data Source may be queried using geo-spatial filters and sorting.
+
+For example, the following code is an an example of finding the three nearest coffee shops.
+
+```js
+CoffeeShop.attachTo(oracle);
+var here = new GeoPoint({lat: 10.32424, lng: 5.84978});
+CoffeeShop.find({where: {location: {near: here}}, limit:3}, function(err, nearbyShops) {
+ console.info(nearbyShops); // [CoffeeShop, ...]
+});
+```
+
+### Distance Types
+
+**Note:** all distance methods use `miles` by default.
+
+ - `miles`
+ - `radians`
+ - `kilometers`
+ - `meters`
+ - `miles`
+ - `feet`
+ - `degrees`
+
+## Methods
+
+### geoPoint.distanceTo(geoPoint, options)
+
+Get the distance to another `GeoPoint`.
+
+```js
+var here = new GeoPoint({lat: 10, lng: 10});
+var there = new GeoPoint({lat: 5, lng: 5});
+console.log(here.distanceTo(there, {type: 'miles'})); // 438
+```
+
+### GeoPoint.distanceBetween(a, b, options)
+
+Get the distance between two points.
+
+```js
+GeoPoint.distanceBetween(here, there, {type: 'miles'}) // 438
+```
+
+## Properties
+
+### geoPoint.lat
+
+The latitude point in degrees. Range: -90 to 90.
+
+### geoPoint.lng
+
+The longitude point in degrees. Range: -180 to 180.
diff --git a/docs/api-model-remote.md b/docs/api-model-remote.md
new file mode 100644
index 000000000..039e17c57
--- /dev/null
+++ b/docs/api-model-remote.md
@@ -0,0 +1,136 @@
+## Remote methods and hooks
+
+You can expose a Model's instance and static methods to clients. A remote method must accept a callback with the conventional `fn(err, result, ...)` signature.
+
+### loopback.remoteMethod(fn, [options])
+
+Expose a remote method.
+
+```js
+Product.stats = function(fn) {
+ var statsResult = {
+ totalPurchased: 123456
+ };
+ var err = null;
+
+ // callback with an error and the result
+ fn(err, statsResult);
+}
+
+loopback.remoteMethod(
+ Product.stats,
+ {
+ returns: {arg: 'stats', type: 'object'},
+ http: {path: '/info', verb: 'get'}
+ }
+);
+```
+
+**Options**
+
+The options argument is a JSON object, described in the following table.
+
+| Option | Required? | Description |
+| ----- | ----- | ----- |
+| accepts | No | Describes the remote method's arguments, as explained below. The callback is an assumed argument; do not specify. |
+| returns | No | Describes the remote method's callback arguments, as explained below.. The err argument is assumed; do not specify. |
+| http | No | HTTP routing information:
- **http.path**: path (relative to the model) at which the method is exposed. May be a path fragment (for example, `/:myArg`) that will be populated by an arg of the same name in the `accepts` description. For example, the `stats` method above will be at the whole path `/products/stats`.
- **http.verb**: HTTP method (verb) from which the method is available (one of: get, post, put, del, or all).
+
+**Argument description**
+
+The arguments description defines either a single argument as an object or an ordered set of arguments as an array. Each individual argument has keys for:
+ * arg: argument name
+ * type: argument datatype; must be a[loopback type](http://wiki.strongloop.com/display/DOC/LoopBack+types).
+ * required: Boolean value indicating if argument is required.
+
+For example, a single argument, specified as an object:
+```js
+{arg: 'myArg', type: 'number'}
+```
+
+Multiple arguments, specified as an array:
+```js
+[
+ {arg: 'arg1', type: 'number', required: true},
+ {arg: 'arg2', type: 'array'}
+]
+```
+
+## Remote hooks
+
+Run a function before or after a remote method is called by a client.
+
+```js
+// *.save === prototype.save
+User.beforeRemote('*.save', function(ctx, user, next) {
+ if(ctx.user) {
+ next();
+ } else {
+ next(new Error('must be logged in to update'))
+ }
+});
+
+User.afterRemote('*.save', function(ctx, user, next) {
+ console.log('user has been saved', user);
+ next();
+});
+```
+
+Remote hooks also support wildcards. Run a function before any remote method is called.
+
+```js
+// ** will match both prototype.* and *.*
+User.beforeRemote('**', function(ctx, user, next) {
+ console.log(ctx.methodString, 'was invoked remotely'); // users.prototype.save was invoked remotely
+ next();
+});
+```
+
+Other wildcard examples
+
+```js
+// run before any static method eg. User.find
+User.beforeRemote('*', ...);
+
+// run before any instance method eg. User.prototype.save
+User.beforeRemote('prototype.*', ...);
+
+// prevent password hashes from being sent to clients
+User.afterRemote('**', function (ctx, user, next) {
+ if(ctx.result) {
+ if(Array.isArray(ctx.result)) {
+ ctx.result.forEach(function (result) {
+ result.password = undefined;
+ });
+ } else {
+ ctx.result.password = undefined;
+ }
+ }
+
+ next();
+});
+```
+
+### Context
+
+Remote hooks are provided with a Context `ctx` object which contains transport specific data (eg. for http: `req` and `res`). The `ctx` object also has a set of consistent apis across transports.
+
+#### ctx.user
+
+A `Model` representing the user calling the method remotely. **Note:** this is undefined if the remote method is not invoked by a logged in user.
+
+#### ctx.result
+
+During `afterRemote` hooks, `ctx.result` will contain the data about to be sent to a client. Modify this object to transform data before it is sent.
+
+#### Rest
+
+When [loopback.rest](#loopbackrest) is used the following `ctx` properties are available.
+
+##### ctx.req
+
+The express ServerRequest object. [See full documentation](http://expressjs.com/api.html#req).
+
+##### ctx.res
+
+The express ServerResponse object. [See full documentation](http://expressjs.com/api.html#res).
diff --git a/docs/api-model.md b/docs/api-model.md
new file mode 100644
index 000000000..3026d5dbb
--- /dev/null
+++ b/docs/api-model.md
@@ -0,0 +1,520 @@
+## Model object
+
+A Loopback `Model` is a vanilla JavaScript class constructor with an attached set of properties and options. A `Model` instance is created by passing a data object containing properties to the `Model` constructor. A `Model` constructor will clean the object passed to it and only set the values matching the properties you define.
+
+```js
+// valid color
+var Color = loopback.createModel('color', {name: String});
+var red = new Color({name: 'red'});
+console.log(red.name); // red
+
+// invalid color
+var foo = new Color({bar: 'bat baz'});
+console.log(foo.bar); // undefined
+```
+
+**Properties**
+
+A model defines a list of property names, types and other validation metadata. A [DataSource](#data-source) uses this definition to validate a `Model` during operations such as `save()`.
+
+**Options**
+
+Some [DataSources](#data-source) may support additional `Model` options.
+
+Define A Loopbackmodel.
+
+```js
+var User = loopback.createModel('user', {
+ first: String,
+ last: String,
+ age: Number
+});
+```
+
+## Methods
+
+### Model.attachTo(dataSource)
+
+Attach a model to a [DataSource](#data-source). Attaching a [DataSource](#data-source) updates the model with additional methods and behaviors.
+
+```js
+var oracle = loopback.createDataSource({
+ connector: require('loopback-connector-oracle'),
+ host: '111.22.333.44',
+ database: 'MYDB',
+ username: 'username',
+ password: 'password'
+});
+
+User.attachTo(oracle);
+```
+
+**Note:** until a model is attached to a data source it will **not** have any **attached methods**.
+
+### Model.validatesFormatOf(property, options)
+
+Require a model to include a property that matches the given format.
+
+```js
+User.validatesFormat('name', {with: /\w+/});
+```
+
+### Model.validatesPresenceOf(properties...)
+
+Require a model to include a property to be considered valid.
+
+```js
+User.validatesPresenceOf('first', 'last', 'age');
+```
+
+### Model.validatesLengthOf(property, options)
+
+Require a property length to be within a specified range.
+
+```js
+User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});
+```
+
+### Model.validatesInclusionOf(property, options)
+
+Require a value for `property` to be in the specified array.
+
+```js
+User.validatesInclusionOf('gender', {in: ['male', 'female']});
+```
+
+### Model.validatesExclusionOf(property, options)
+
+Require a value for `property` to not exist in the specified array.
+
+```js
+User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
+```
+
+### Model.validatesNumericalityOf(property, options)
+
+Require a value for `property` to be a specific type of `Number`.
+
+```js
+User.validatesNumericalityOf('age', {int: true});
+```
+
+### Model.validatesUniquenessOf(property, options)
+
+Ensure the value for `property` is unique in the collection of models.
+
+```js
+User.validatesUniquenessOf('email', {message: 'email is not unique'});
+```
+
+**Note:** not available for all [connectors](#connectors).
+
+Currently supported in these connectors:
+
+ - [In Memory](#memory-connector)
+ - [Oracle](http://github.com/strongloop/loopback-connector-oracle)
+ - [MongoDB](http://github.com/strongloop/loopback-connector-mongodb)
+
+### myModel.isValid()
+
+Validate the model instance.
+
+```js
+user.isValid(function (valid) {
+ if (!valid) {
+ console.log(user.errors);
+ // => hash of errors
+ // => {
+ // => username: [errmessage, errmessage, ...],
+ // => email: ...
+ // => }
+ }
+});
+```
+## Properties
+
+### Model.properties
+
+An object containing a normalized set of properties supplied to `loopback.createModel(name, properties)`.
+
+Example:
+
+```js
+var props = {
+ a: String,
+ b: {type: 'Number'},
+ c: {type: 'String', min: 10, max: 100},
+ d: Date,
+ e: loopback.GeoPoint
+};
+
+var MyModel = loopback.createModel('foo', props);
+
+console.log(MyModel.properties);
+```
+
+Outputs:
+
+```js
+{
+ "a": {type: String},
+ "b": {type: Number},
+ "c": {
+ "type": String,
+ "min": 10,
+ "max": 100
+ },
+ "d": {type: Date},
+ "e": {type: GeoPoint},
+ "id": {
+ "id": 1
+ }
+}
+```
+
+## CRUD and Query Mixins
+
+Mixins are added by attaching a vanilla model to a [data source](#data-source) with a [connector](#connectors). Each [connector](#connectors) enables its own set of operations that are mixed into a `Model` as methods. To see available methods for a data source call `dataSource.operations()`.
+
+Log the available methods for a memory data source.
+
+```js
+var ops = loopback
+ .createDataSource({connector: loopback.Memory})
+ .operations();
+
+console.log(Object.keys(ops));
+```
+
+Outputs:
+
+```js
+[ 'create',
+ 'updateOrCreate',
+ 'upsert',
+ 'findOrCreate',
+ 'exists',
+ 'findById',
+ 'find',
+ 'all',
+ 'findOne',
+ 'destroyAll',
+ 'deleteAll',
+ 'count',
+ 'include',
+ 'relationNameFor',
+ 'hasMany',
+ 'belongsTo',
+ 'hasAndBelongsToMany',
+ 'save',
+ 'isNewRecord',
+ 'destroy',
+ 'delete',
+ 'updateAttribute',
+ 'updateAttributes',
+ 'reload' ]
+```
+
+Here is the definition of the `count()` operation.
+
+```js
+{
+ accepts: [ { arg: 'where', type: 'object' } ],
+ http: { verb: 'get', path: '/count' },
+ remoteEnabled: true,
+ name: 'count'
+}
+```
+
+## Static Methods
+
+**Note:** These are the default mixin methods for a `Model` attached to a data source. See the specific connector for additional API documentation.
+
+### Model.create(data, [callback])
+
+Create an instance of Model with given data and save to the attached data source. Callback is optional.
+
+```js
+User.create({first: 'Joe', last: 'Bob'}, function(err, user) {
+ console.log(user instanceof User); // true
+});
+```
+
+**Note:** You must include a callback and use the created model provided in the callback if your code depends on your model being saved or having an `id`.
+
+### Model.count([query], callback)
+
+Query count of Model instances in data source. Optional query param allows to count filtered set of Model instances.
+
+```js
+User.count({approved: true}, function(err, count) {
+ console.log(count); // 2081
+});
+```
+
+### Model.find(filter, callback)
+
+Find all instances of Model, matched by query. Fields used for filter and sort should be declared with `{index: true}` in model definition.
+
+**filter**
+
+ - **where** `Object` { key: val, key2: {gt: 'val2'}} The search criteria
+ - Format: {key: val} or {key: {op: val}}
+ - Operations:
+ - gt: >
+ - gte: >=
+ - lt: <
+ - lte: <=
+ - between
+ - inq: IN
+ - nin: NOT IN
+ - neq: !=
+ - like: LIKE
+ - nlike: NOT LIKE
+
+ - **include** `String`, `Object` or `Array` Allows you to load relations of several objects and optimize numbers of requests.
+ - Format:
+ - 'posts': Load posts
+ - ['posts', 'passports']: Load posts and passports
+ - {'owner': 'posts'}: Load owner and owner's posts
+ - {'owner': ['posts', 'passports']}: Load owner, owner's posts, and owner's passports
+ - {'owner': [{posts: 'images'}, 'passports']}: Load owner, owner's posts, owner's posts' images, and owner's passports
+
+ - **order** `String` The sorting order
+ - Format: 'key1 ASC, key2 DESC'
+
+ - **limit** `Number` The maximum number of instances to be returned
+ - **skip** `Number` Skip the number of instances
+ - **offset** `Number` Alias for skip
+
+ - **fields** `Object|Array|String` The included/excluded fields
+ - `['foo']` or `'foo'` - include only the foo property
+ - `['foo', 'bar']` - include the foo and bar properties
+ - `{foo: true}` - include only foo
+ - `{bat: false}` - include all properties, exclude bat
+
+Find the second page of 10 users over age 21 in descending order exluding the password property.
+
+```js
+User.find({
+ where: {
+ age: {gt: 21}},
+ order: 'age DESC',
+ limit: 10,
+ skip: 10,
+ fields: {password: false}
+ },
+ console.log
+);
+```
+
+**Note:** See the specific connector's [docs](#connectors) for more info.
+
+### Model.destroyAll(callback)
+
+Delete all Model instances from data source. **Note:** destroyAll method does not perform destroy hooks.
+
+### Model.findById(id, callback)
+
+Find instance by id.
+
+```js
+User.findById(23, function(err, user) {
+ console.info(user.id); // 23
+});
+```
+
+### Model.findOne(where, callback)
+
+Find a single instance that matches the given where expression.
+
+```js
+User.findOne({id: 23}, function(err, user) {
+ console.info(user.id); // 23
+});
+```
+
+### Model.upsert(data, callback)
+
+Update when record with id=data.id found, insert otherwise. **Note:** no setters, validations or hooks applied when using upsert.
+
+### Custom static methods
+
+Define a static model method.
+
+```js
+User.login = function (username, password, fn) {
+ var passwordHash = hashPassword(password);
+ this.findOne({username: username}, function (err, user) {
+ var failErr = new Error('login failed');
+
+ if(err) {
+ fn(err);
+ } else if(!user) {
+ fn(failErr);
+ } else if(user.password === passwordHash) {
+ MyAccessTokenModel.create({userId: user.id}, function (err, accessToken) {
+ fn(null, accessToken.id);
+ });
+ } else {
+ fn(failErr);
+ }
+ });
+}
+```
+
+Setup the static model method to be exposed to clients as a [remote method](#remote-method).
+
+```js
+loopback.remoteMethod(
+ User.login,
+ {
+ accepts: [
+ {arg: 'username', type: 'string', required: true},
+ {arg: 'password', type: 'string', required: true}
+ ],
+ returns: {arg: 'sessionId', type: 'any'},
+ http: {path: '/sign-in'}
+ }
+);
+```
+
+## Instance methods
+
+**Note:** These are the default mixin methods for a `Model` attached to a data source. See the specific connector for additional API documentation.
+
+### model.save([options], [callback])
+
+Save an instance of a Model to the attached data source.
+
+```js
+var joe = new User({first: 'Joe', last: 'Bob'});
+joe.save(function(err, user) {
+ if(user.errors) {
+ console.log(user.errors);
+ } else {
+ console.log(user.id);
+ }
+});
+```
+
+### model.updateAttributes(data, [callback])
+
+Save specified attributes to the attached data source.
+
+```js
+user.updateAttributes({
+ first: 'updatedFirst',
+ name: 'updatedLast'
+}, fn);
+```
+
+### model.destroy([callback])
+
+Remove a model from the attached data source.
+
+```js
+model.destroy(function(err) {
+ // model instance destroyed
+});
+```
+
+### Custom instance methods
+
+Define an instance method.
+
+```js
+User.prototype.logout = function (fn) {
+ MySessionModel.destroyAll({userId: this.id}, fn);
+}
+```
+
+Define a remote model instance method.
+
+```js
+loopback.remoteMethod(User.prototype.logout)
+```
+
+## Relationships
+
+### Model.hasMany(Model, options)
+
+Define a "one to many" relationship.
+
+```js
+// by referencing model
+Book.hasMany(Chapter);
+// specify the name
+Book.hasMany('chapters', {model: Chapter});
+```
+
+Query and create the related models.
+
+```js
+Book.create(function(err, book) {
+ // create a chapter instance
+ // ready to be saved in the data source
+ var chapter = book.chapters.build({name: 'Chapter 1'});
+
+ // save the new chapter
+ chapter.save();
+
+ // you can also call the Chapter.create method with
+ // the `chapters` property which will build a chapter
+ // instance and save the it in the data source
+ book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
+ // this callback is optional
+ });
+
+ // query chapters for the book using the
+ book.chapters(function(err, chapters) {
+ // all chapters with bookId = book.id
+ console.log(chapters);
+ });
+
+ book.chapters({where: {name: 'test'}, function(err, chapters) {
+ // all chapters with bookId = book.id and name = 'test'
+ console.log(chapters);
+ });
+});
+```
+
+### Model.belongsTo(Model, options)
+
+A `belongsTo` relation sets up a one-to-one connection with another model, such
+that each instance of the declaring model "belongs to" one instance of the other
+model. For example, if your application includes users and posts, and each post
+can be written by exactly one user.
+
+```js
+ Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
+```
+
+The code above basically says Post has a reference called `author` to User using
+the `userId` property of Post as the foreign key. Now we can access the author
+in one of the following styles:
+
+```js
+ post.author(callback); // Get the User object for the post author asynchronously
+ post.author(); // Get the User object for the post author synchronously
+ post.author(user) // Set the author to be the given user
+```
+
+### Model.hasAndBelongsToMany(Model, options)
+
+A `hasAndBelongsToMany` relation creates a direct many-to-many connection with
+another model, with no intervening model. For example, if your application
+includes users and groups, with each group having many users and each user
+appearing in many groups, you could declare the models this way,
+
+```js
+ User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'});
+ user.groups(callback); // get groups of the user
+ user.groups.create(data, callback); // create a new group and connect it with the user
+ user.groups.add(group, callback); // connect an existing group with the user
+ user.groups.remove(group, callback); // remove the user from the group
+```
+
+## Shared methods
+
+Any static or instance method can be decorated as `shared`. These methods are exposed over the provided transport (eg. [loopback.rest](#rest)).
diff --git a/docs/api.md b/docs/api.md
index 413f821a3..36692f84d 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -1,1215 +1,7 @@
## Node.js API
-### App
-
-Create a Loopback application.
-
-```js
-var loopback = require('loopback');
-var app = loopback();
-
-app.get('/', function(req, res){
- res.send('hello world');
-});
-
-app.listen(3000);
-```
-
-> **Notes**
->
-> - extends [express](http://expressjs.com/api.html#express)
-> - see [express docs](http://expressjs.com/api.html) for details
-> - supports [express / connect middleware](http://expressjs.com/api.html#middleware)
-
-#### app.boot([options])
-
-Initialize an application from an options object or a set of JSON and JavaScript files.
-
-**What happens during an app _boot_?**
-
-1. **DataSources** are created from an `options.dataSources` object or `datasources.json` in the current directory
-2. **Models** are created from an `options.models` object or `models.json` in the current directory
-3. Any JavaScript files in the `./models` directory are loaded with `require()`.
-
-**Options**
-
- - `cwd` - _optional_ - the directory to use when loading JSON and JavaScript files
- - `models` - _optional_ - an object containing `Model` definitions
- - `dataSources` - _optional_ - an object containing `DataSource` definitions
-
-> **NOTE:** mixing `app.boot()` and `app.model(name, config)` in multiple files may result
-> in models being **undefined** due to race conditions. To avoid this when using `app.boot()`
-> make sure all models are passed as part of the `models` definition.
-
-
-**Model Definitions**
-
-The following is an example of an object containing two `Model` definitions: "location" and "inventory".
-
-```js
-{
- "dealership": {
- // a reference, by name, to a dataSource definition
- "dataSource": "my-db",
- // the options passed to Model.extend(name, properties, options)
- "options": {
- "relationships": {
- "cars": {
- "type": "hasMany",
- "model": "Car",
- "foreignKey": "dealerId"
- }
- },
- "remoteMethods": {
- "nearby": {
- "description": "Find nearby locations around the geo point",
- "accepts": [
- {"arg": "here", "type": "GeoPoint", "required": true, "description": "geo location (lat & lng)"}
- ],
- "returns": {"arg": "locations", "root": true}
- }
- }
- },
- // the properties passed to Model.extend(name, properties, options)
- "properties": {
- "id": {"id": true},
- "name": "String",
- "zip": "Number",
- "address": "String"
- }
- },
- "car": {
- "dataSource": "my-db"
- "properties": {
- "id": {
- "type": "String",
- "required": true,
- "id": true
- },
- "make": {
- "type": "String",
- "required": true
- },
- "model": {
- "type": "String",
- "required": true
- }
- }
- }
-}
-```
-
-**Model Definition Properties**
-
- - `dataSource` - **required** - a string containing the name of the data source definition to attach the `Model` to
- - `options` - _optional_ - an object containing `Model` options
- - `properties` _optional_ - an object defining the `Model` properties in [LoopBack Definition Language](http://docs.strongloop.com/loopback-datasource-juggler/#loopback-definition-language)
-
-**DataSource Definition Properties**
-
- - `connector` - **required** - the name of the [connector](#working-with-data-sources-and-connectors)
-
-#### app.model(name, definition)
-
-Define a `Model` and export it for use by remote clients.
-
-```js
-// declare a DataSource
-app.boot({
- dataSources: {
- db: {
- connector: 'mongodb',
- url: 'mongodb://localhost:27015/my-database-name'
- }
- }
-});
-
-// describe a model
-var modelDefinition = {dataSource: 'db'};
-
-// create the model
-var Product = app.model('product', modelDefinition);
-
-// use the model api
-Product.create({name: 'pencil', price: 0.99}, console.log);
-```
-
-> **Note** - this will expose all [shared methods](#shared-methods) on the model.
-
-You may also export an existing `Model` by calling `app.model(Model)` like the example below.
-
-#### app.models.MyModel
-
-All models are avaialbe from the `loopback.models` object. In the following
-example the `Product` and `CustomerReceipt` models are accessed using
-the `models` object.
-
-> **NOTE:** you must call `app.boot()` in order to build the app.models object.
-
-```js
-var loopback = require('loopback');
-var app = loopback();
-app.boot({
- dataSources: {
- db: {connector: 'memory'}
- }
-});
-app.model('product', {dataSource: 'db'});
-app.model('customer-receipt', {dataSource: 'db'});
-
-// available based on the given name
-var Product = app.models.Product;
-
-// also available as camelCase
-var product = app.models.product;
-
-// multi-word models are avaiable as pascal cased
-var CustomerReceipt = app.models.CustomerReceipt;
-
-// also available as camelCase
-var customerReceipt = app.models.customerReceipt;
-```
-
-#### app.models()
-
-Get the app's exported models. Only models defined using `app.model()` will show up in this list.
-
-```js
-var models = app.models();
-
-models.forEach(function (Model) {
- console.log(Model.modelName); // color
-});
-```
-
-#### app.docs(options)
-
-Enable swagger REST API documentation.
-
-**Options**
-
- - `basePath` The basepath for your API - eg. 'http://localhost:3000'.
-
-**Example**
-
-```js
-// enable docs
-app.docs({basePath: 'http://localhost:3000'});
-```
-
-Run your app then navigate to [the api explorer](http://petstore.swagger.wordnik.com/). Enter your API basepath to view your generated docs.
-
-#### app.use( router )
-
-Expose models over specified router.
-For example, to expose models over REST using the `loopback.rest` router:
-
-```js
-app.use(loopback.rest());
-```
-
-View generated REST documentation by visiting: [http://localhost:3000/_docs](http://localhost:3000/_docs).
-
-
-### Model
-
-A Loopback `Model` is a vanilla JavaScript class constructor with an attached set of properties and options. A `Model` instance is created by passing a data object containing properties to the `Model` constructor. A `Model` constructor will clean the object passed to it and only set the values matching the properties you define.
-
-```js
-// valid color
-var Color = loopback.createModel('color', {name: String});
-var red = new Color({name: 'red'});
-console.log(red.name); // red
-
-// invalid color
-var foo = new Color({bar: 'bat baz'});
-console.log(foo.bar); // undefined
-```
-
-**Properties**
-
-A model defines a list of property names, types and other validation metadata. A [DataSource](#data-source) uses this definition to validate a `Model` during operations such as `save()`.
-
-**Options**
-
-Some [DataSources](#data-source) may support additional `Model` options.
-
-Define A Loopbackmodel.
-
-```js
-var User = loopback.createModel('user', {
- first: String,
- last: String,
- age: Number
-});
-```
-
-#### Validation (expiremental)
-
-##### Model.validatesFormatOf(property, options)
-
-Require a model to include a property that matches the given format.
-
-```js
-User.validatesFormat('name', {with: /\w+/});
-```
-
-##### Model.validatesPresenceOf(properties...)
-
-Require a model to include a property to be considered valid.
-
-```js
-User.validatesPresenceOf('first', 'last', 'age');
-```
-
-##### Model.validatesLengthOf(property, options)
-
-Require a property length to be within a specified range.
-
-```js
-User.validatesLengthOf('password', {min: 5, message: {min: 'Password is too short'}});
-```
-
-##### Model.validatesInclusionOf(property, options)
-
-Require a value for `property` to be in the specified array.
-
-```js
-User.validatesInclusionOf('gender', {in: ['male', 'female']});
-```
-
-##### Model.validatesExclusionOf(property, options)
-
-Require a value for `property` to not exist in the specified array.
-
-```js
-User.validatesExclusionOf('domain', {in: ['www', 'billing', 'admin']});
-```
-
-##### Model.validatesNumericalityOf(property, options)
-
-Require a value for `property` to be a specific type of `Number`.
-
-```js
-User.validatesNumericalityOf('age', {int: true});
-```
-
-##### Model.validatesUniquenessOf(property, options)
-
-Ensure the value for `property` is unique in the collection of models.
-
-```js
-User.validatesUniquenessOf('email', {message: 'email is not unique'});
-```
-
-**Note:** not available for all [connectors](#connectors).
-
-Currently supported in these connectors:
-
- - [In Memory](#memory-connector)
- - [Oracle](http://github.com/strongloop/loopback-connector-oracle)
- - [MongoDB](http://github.com/strongloop/loopback-connector-mongodb)
-
-##### myModel.isValid()
-
-Validate the model instance.
-
-```js
-user.isValid(function (valid) {
- if (!valid) {
- console.log(user.errors);
- // => hash of errors
- // => {
- // => username: [errmessage, errmessage, ...],
- // => email: ...
- // => }
- }
-});
-```
-
-#### Model.properties
-
-An object containing a normalized set of properties supplied to `loopback.createModel(name, properties)`.
-
-Example:
-
-```js
-var props = {
- a: String,
- b: {type: 'Number'},
- c: {type: 'String', min: 10, max: 100},
- d: Date,
- e: loopback.GeoPoint
-};
-
-var MyModel = loopback.createModel('foo', props);
-
-console.log(MyModel.properties);
-```
-
-Outputs:
-
-```js
-{
- "a": {type: String},
- "b": {type: Number},
- "c": {
- "type": String,
- "min": 10,
- "max": 100
- },
- "d": {type: Date},
- "e": {type: GeoPoint},
- "id": {
- "id": 1
- }
-}
-```
-
-#### Model.attachTo(dataSource)
-
-Attach a model to a [DataSource](#data-source). Attaching a [DataSource](#data-source) updates the model with additional methods and behaviors.
-
-```js
-var oracle = loopback.createDataSource({
- connector: require('loopback-connector-oracle'),
- host: '111.22.333.44',
- database: 'MYDB',
- username: 'username',
- password: 'password'
-});
-
-User.attachTo(oracle);
-```
-
-**Note:** until a model is attached to a data source it will **not** have any **attached methods**.
-
-#### CRUD and Query Mixins
-
-Mixins are added by attaching a vanilla model to a [data source](#data-source) with a [connector](#connectors). Each [connector](#connectors) enables its own set of operations that are mixed into a `Model` as methods. To see available methods for a data source call `dataSource.operations()`.
-
-Log the available methods for a memory data source.
-
-```js
-var ops = loopback
- .createDataSource({connector: loopback.Memory})
- .operations();
-
-console.log(Object.keys(ops));
-```
-
-Outputs:
-
-```js
-[ 'create',
- 'updateOrCreate',
- 'upsert',
- 'findOrCreate',
- 'exists',
- 'findById',
- 'find',
- 'all',
- 'findOne',
- 'destroyAll',
- 'deleteAll',
- 'count',
- 'include',
- 'relationNameFor',
- 'hasMany',
- 'belongsTo',
- 'hasAndBelongsToMany',
- 'save',
- 'isNewRecord',
- 'destroy',
- 'delete',
- 'updateAttribute',
- 'updateAttributes',
- 'reload' ]
-```
-
-Here is the definition of the `count()` operation.
-
-```js
-{
- accepts: [ { arg: 'where', type: 'object' } ],
- http: { verb: 'get', path: '/count' },
- remoteEnabled: true,
- name: 'count'
-}
-```
-
-#### Static Methods
-
-**Note:** These are the default mixin methods for a `Model` attached to a data source. See the specific connector for additional API documentation.
-
-##### Model.create(data, [callback])
-
-Create an instance of Model with given data and save to the attached data source. Callback is optional.
-
-```js
-User.create({first: 'Joe', last: 'Bob'}, function(err, user) {
- console.log(user instanceof User); // true
-});
-```
-
-**Note:** You must include a callback and use the created model provided in the callback if your code depends on your model being saved or having an `id`.
-
-##### Model.count([query], callback)
-
-Query count of Model instances in data source. Optional query param allows to count filtered set of Model instances.
-
-```js
-User.count({approved: true}, function(err, count) {
- console.log(count); // 2081
-});
-```
-
-##### Model.find(filter, callback)
-
-Find all instances of Model, matched by query. Fields used for filter and sort should be declared with `{index: true}` in model definition.
-
-**filter**
-
- - **where** `Object` { key: val, key2: {gt: 'val2'}} The search criteria
- - Format: {key: val} or {key: {op: val}}
- - Operations:
- - gt: >
- - gte: >=
- - lt: <
- - lte: <=
- - between
- - inq: IN
- - nin: NOT IN
- - neq: !=
- - like: LIKE
- - nlike: NOT LIKE
-
- - **include** `String`, `Object` or `Array` Allows you to load relations of several objects and optimize numbers of requests.
- - Format:
- - 'posts': Load posts
- - ['posts', 'passports']: Load posts and passports
- - {'owner': 'posts'}: Load owner and owner's posts
- - {'owner': ['posts', 'passports']}: Load owner, owner's posts, and owner's passports
- - {'owner': [{posts: 'images'}, 'passports']}: Load owner, owner's posts, owner's posts' images, and owner's passports
-
- - **order** `String` The sorting order
- - Format: 'key1 ASC, key2 DESC'
-
- - **limit** `Number` The maximum number of instances to be returned
- - **skip** `Number` Skip the number of instances
- - **offset** `Number` Alias for skip
-
- - **fields** `Object|Array|String` The included/excluded fields
- - `['foo']` or `'foo'` - include only the foo property
- - `['foo', 'bar']` - include the foo and bar properties
- - `{foo: true}` - include only foo
- - `{bat: false}` - include all properties, exclude bat
-
-Find the second page of 10 users over age 21 in descending order exluding the password property.
-
-```js
-User.find({
- where: {
- age: {gt: 21}},
- order: 'age DESC',
- limit: 10,
- skip: 10,
- fields: {password: false}
- },
- console.log
-);
-```
-
-**Note:** See the specific connector's [docs](#connectors) for more info.
-
-##### Model.destroyAll(callback)
-
-Delete all Model instances from data source. **Note:** destroyAll method does not perform destroy hooks.
-
-##### Model.findById(id, callback)
-
-Find instance by id.
-
-```js
-User.findById(23, function(err, user) {
- console.info(user.id); // 23
-});
-```
-
-##### Model.findOne(where, callback)
-
-Find a single instance that matches the given where expression.
-
-```js
-User.findOne({id: 23}, function(err, user) {
- console.info(user.id); // 23
-});
-```
-
-##### Model.upsert(data, callback)
-
-Update when record with id=data.id found, insert otherwise. **Note:** no setters, validations or hooks applied when using upsert.
-
-##### Custom Static Methods
-
-Define a static model method.
-
-```js
-User.login = function (username, password, fn) {
- var passwordHash = hashPassword(password);
- this.findOne({username: username}, function (err, user) {
- var failErr = new Error('login failed');
-
- if(err) {
- fn(err);
- } else if(!user) {
- fn(failErr);
- } else if(user.password === passwordHash) {
- MySessionModel.create({userId: user.id}, function (err, session) {
- fn(null, session.id);
- });
- } else {
- fn(failErr);
- }
- });
-}
-```
-
-Setup the static model method to be exposed to clients as a [remote method](#remote-method).
-
-```js
-loopback.remoteMethod(
- User.login,
- {
- accepts: [
- {arg: 'username', type: 'string', required: true},
- {arg: 'password', type: 'string', required: true}
- ],
- returns: {arg: 'sessionId', type: 'any'},
- http: {path: '/sign-in'}
- }
-);
-```
-
-#### Instance Methods
-
-**Note:** These are the default mixin methods for a `Model` attached to a data source. See the specific connector for additional API documentation.
-
-##### model.save([options], [callback])
-
-Save an instance of a Model to the attached data source.
-
-```js
-var joe = new User({first: 'Joe', last: 'Bob'});
-joe.save(function(err, user) {
- if(user.errors) {
- console.log(user.errors);
- } else {
- console.log(user.id);
- }
-});
-```
-
-##### model.updateAttributes(data, [callback])
-
-Save specified attributes to the attached data source.
-
-```js
-user.updateAttributes({
- first: 'updatedFirst',
- name: 'updatedLast'
-}, fn);
-```
-
-##### model.destroy([callback])
-
-Remove a model from the attached data source.
-
-```js
-model.destroy(function(err) {
- // model instance destroyed
-});
-```
-
-##### Custom Instance Methods
-
-Define an instance method.
-
-```js
-User.prototype.logout = function (fn) {
- MySessionModel.destroyAll({userId: this.id}, fn);
-}
-```
-
-Define a remote model instance method.
-
-```js
-loopback.remoteMethod(User.prototype.logout)
-```
-
-#### Remote Methods
-
-Both instance and static methods can be exposed to clients. A remote method must accept a callback with the conventional `fn(err, result, ...)` signature.
-
-##### loopback.remoteMethod(fn, [options])
-
-Expose a remote method.
-
-```js
-Product.stats = function(fn) {
- var statsResult = {
- totalPurchased: 123456
- };
- var err = null;
-
- // callback with an error and the result
- fn(err, statsResult);
-}
-
-loopback.remoteMethod(
- Product.stats,
- {
- returns: {arg: 'stats', type: 'object'},
- http: {path: '/info', verb: 'get'}
- }
-);
-```
-
-**Options**
-
- - **accepts** - (optional) an arguments description specifying the remote method's arguments.
- - **returns** - (optional) an arguments description specifying the remote methods callback arguments.
- - **http** - (advanced / optional, object) http routing info
- - **http.path** - the path relative to the model the method will be exposed at. May be a path fragment (eg. '/:myArg') which will be populated by an arg of the same name in the accepts description. For example the stats method above will be at the whole path `/products/stats`.
- - **http.verb** - (get, post, put, del, all) - the route verb the method will be available from.
-
-**Argument Description**
-
-An arguments description defines either a single argument as an object or an ordered set of arguments as an array.
-
-```js
-// examples
-{arg: 'myArg', type: 'number'}
-
-[
- {arg: 'arg1', type: 'number', required: true},
- {arg: 'arg2', type: 'array'}
-]
-```
-
-**Types**
-
-Each argument may define any of the [loopback types](#loopback-types).
-
-**Notes:**
-
- - The callback is an assumed argument and does not need to be specified in the accepts array.
- - The err argument is also assumed and does not need to be specified in the returns array.
-
-#### Remote Hooks
-
-Run a function before or after a remote method is called by a client.
-
-```js
-// *.save === prototype.save
-User.beforeRemote('*.save', function(ctx, user, next) {
- if(ctx.user) {
- next();
- } else {
- next(new Error('must be logged in to update'))
- }
-});
-
-User.afterRemote('*.save', function(ctx, user, next) {
- console.log('user has been saved', user);
- next();
-});
-```
-
-Remote hooks also support wildcards. Run a function before any remote method is called.
-
-```js
-// ** will match both prototype.* and *.*
-User.beforeRemote('**', function(ctx, user, next) {
- console.log(ctx.methodString, 'was invoked remotely'); // users.prototype.save was invoked remotely
- next();
-});
-```
-
-Other wildcard examples
-
-```js
-// run before any static method eg. User.find
-User.beforeRemote('*', ...);
-
-// run before any instance method eg. User.prototype.save
-User.beforeRemote('prototype.*', ...);
-
-// prevent password hashes from being sent to clients
-User.afterRemote('**', function (ctx, user, next) {
- if(ctx.result) {
- if(Array.isArray(ctx.result)) {
- ctx.result.forEach(function (result) {
- result.password = undefined;
- });
- } else {
- ctx.result.password = undefined;
- }
- }
-
- next();
-});
-```
-
-#### Context
-
-Remote hooks are provided with a Context `ctx` object which contains transport specific data (eg. for http: `req` and `res`). The `ctx` object also has a set of consistent apis across transports.
-
-##### ctx.user
-
-A `Model` representing the user calling the method remotely. **Note:** this is undefined if the remote method is not invoked by a logged in user.
-
-##### ctx.result
-
-During `afterRemote` hooks, `ctx.result` will contain the data about to be sent to a client. Modify this object to transform data before it is sent.
-
-##### Rest
-
-When [loopback.rest](#loopbackrest) is used the following `ctx` properties are available.
-
-###### ctx.req
-
-The express ServerRequest object. [See full documentation](http://expressjs.com/api.html#req).
-
-###### ctx.res
-
-The express ServerResponse object. [See full documentation](http://expressjs.com/api.html#res).
-
-#### Relationships
-
-##### Model.hasMany(Model, options)
-
-Define a "one to many" relationship.
-
-```js
-// by referencing model
-Book.hasMany(Chapter);
-// specify the name
-Book.hasMany('chapters', {model: Chapter});
-```
-
-Query and create the related models.
-
-```js
-Book.create(function(err, book) {
- // create a chapter instance
- // ready to be saved in the data source
- var chapter = book.chapters.build({name: 'Chapter 1'});
-
- // save the new chapter
- chapter.save();
-
- // you can also call the Chapter.create method with
- // the `chapters` property which will build a chapter
- // instance and save the it in the data source
- book.chapters.create({name: 'Chapter 2'}, function(err, savedChapter) {
- // this callback is optional
- });
-
- // query chapters for the book using the
- book.chapters(function(err, chapters) {
- // all chapters with bookId = book.id
- console.log(chapters);
- });
-
- book.chapters({where: {name: 'test'}, function(err, chapters) {
- // all chapters with bookId = book.id and name = 'test'
- console.log(chapters);
- });
-});
-```
-
-##### Model.belongsTo(Model, options)
-
-A `belongsTo` relation sets up a one-to-one connection with another model, such
-that each instance of the declaring model "belongs to" one instance of the other
-model. For example, if your application includes users and posts, and each post
-can be written by exactly one user.
-
-```js
- Post.belongsTo(User, {as: 'author', foreignKey: 'userId'});
-```
-
-The code above basically says Post has a reference called `author` to User using
-the `userId` property of Post as the foreign key. Now we can access the author
-in one of the following styles:
-
-```js
- post.author(callback); // Get the User object for the post author asynchronously
- post.author(); // Get the User object for the post author synchronously
- post.author(user) // Set the author to be the given user
-```
-
-##### Model.hasAndBelongsToMany(Model, options)
-
-A `hasAndBelongsToMany` relation creates a direct many-to-many connection with
-another model, with no intervening model. For example, if your application
-includes users and groups, with each group having many users and each user
-appearing in many groups, you could declare the models this way,
-
-```js
- User.hasAndBelongsToMany('groups', {model: Group, foreignKey: 'groupId'});
- user.groups(callback); // get groups of the user
- user.groups.create(data, callback); // create a new group and connect it with the user
- user.groups.add(group, callback); // connect an existing group with the user
- user.groups.remove(group, callback); // remove the user from the group
-```
-
-#### Shared Methods
-
-Any static or instance method can be decorated as `shared`. These methods are exposed over the provided transport (eg. [loopback.rest](#rest)).
-
-### Data Source
-
-A Loopback `DataSource` provides [Models](#model) with the ability to manipulate data. Attaching a `DataSource` to a `Model` adds [instance methods](#instance-methods) and [static methods](#static-methods) to the `Model`. The added methods may be [remote methods](#remote-methods).
-
-Define a data source for persisting models.
-
-```js
-var oracle = loopback.createDataSource({
- connector: 'oracle',
- host: '111.22.333.44',
- database: 'MYDB',
- username: 'username',
- password: 'password'
-});
-```
-
-#### dataSource.createModel(name, properties, options)
-
-Define a model and attach it to a `DataSource`.
-
-```js
-var Color = oracle.createModel('color', {name: String});
-```
-
-#### dataSource.discoverModelDefinitions([username], fn)
-
-Discover a set of model definitions (table or collection names) based on tables or collections in a data source.
-
-```js
-oracle.discoverModelDefinitions(function (err, models) {
- models.forEach(function (def) {
- // def.name ~ the model name
- oracle.discoverSchema(null, def.name, function (err, schema) {
- console.log(schema);
- });
- });
-});
-```
-
-#### dataSource.discoverSchema([owner], name, fn)
-
-Discover the schema of a specific table or collection.
-
-**Example schema from oracle connector:**
-
-```js
- {
- "name": "Product",
- "options": {
- "idInjection": false,
- "oracle": {
- "schema": "BLACKPOOL",
- "table": "PRODUCT"
- }
- },
- "properties": {
- "id": {
- "type": "String",
- "required": true,
- "length": 20,
- "id": 1,
- "oracle": {
- "columnName": "ID",
- "dataType": "VARCHAR2",
- "dataLength": 20,
- "nullable": "N"
- }
- },
- "name": {
- "type": "String",
- "required": false,
- "length": 64,
- "oracle": {
- "columnName": "NAME",
- "dataType": "VARCHAR2",
- "dataLength": 64,
- "nullable": "Y"
- }
- },
- "audibleRange": {
- "type": "Number",
- "required": false,
- "length": 22,
- "oracle": {
- "columnName": "AUDIBLE_RANGE",
- "dataType": "NUMBER",
- "dataLength": 22,
- "nullable": "Y"
- }
- },
- "effectiveRange": {
- "type": "Number",
- "required": false,
- "length": 22,
- "oracle": {
- "columnName": "EFFECTIVE_RANGE",
- "dataType": "NUMBER",
- "dataLength": 22,
- "nullable": "Y"
- }
- },
- "rounds": {
- "type": "Number",
- "required": false,
- "length": 22,
- "oracle": {
- "columnName": "ROUNDS",
- "dataType": "NUMBER",
- "dataLength": 22,
- "nullable": "Y"
- }
- },
- "extras": {
- "type": "String",
- "required": false,
- "length": 64,
- "oracle": {
- "columnName": "EXTRAS",
- "dataType": "VARCHAR2",
- "dataLength": 64,
- "nullable": "Y"
- }
- },
- "fireModes": {
- "type": "String",
- "required": false,
- "length": 64,
- "oracle": {
- "columnName": "FIRE_MODES",
- "dataType": "VARCHAR2",
- "dataLength": 64,
- "nullable": "Y"
- }
- }
- }
- }
-```
-
-#### dataSource.enableRemote(operation)
-
-Enable remote access to a data source operation. Each [connector](#connector) has its own set of set remotely enabled and disabled operations. You can always list these by calling `dataSource.operations()`.
-
-
-#### dataSource.disableRemote(operation)
-
-Disable remote access to a data source operation. Each [connector](#connector) has its own set of set enabled and disabled operations. You can always list these by calling `dataSource.operations()`.
-
-```js
-// all rest data source operations are
-// disabled by default
-var oracle = loopback.createDataSource({
- connector: require('loopback-connector-oracle'),
- host: '...',
- ...
-});
-
-// or only disable it as a remote method
-oracle.disableRemote('destroyAll');
-```
-
-**Notes:**
-
- - disabled operations will not be added to attached models
- - disabling the remoting for a method only affects client access (it will still be available from server models)
- - data sources must enable / disable operations before attaching or creating models
-
-#### dataSource.operations()
-
-List the enabled and disabled operations.
-
- console.log(oracle.operations());
-
-Output:
-
-```js
-{
- find: {
- remoteEnabled: true,
- accepts: [...],
- returns: [...]
- enabled: true
- },
- save: {
- remoteEnabled: true,
- prototype: true,
- accepts: [...],
- returns: [...],
- enabled: true
- },
- ...
-}
-```
-
-#### Connectors
-
-Create a data source with a specific connector. See **available connectors** for specific connector documentation.
-
-```js
-var memory = loopback.createDataSource({
- connector: loopback.Memory
-});
-```
-
-**Database Connectors**
-
- - [In Memory](#memory-connector)
- - [Oracle](http://github.com/strongloop/loopback-connector-oracle)
- - [MongoDB](http://github.com/strongloop/loopback-connector-mongodb)
- - [MySQL](http://github.com/strongloop/loopback-connector-mysql) - In Development
- - [SQLite3](http://github.com/strongloop/loopback-connector-sqlite) - In Development
- - [Postgres](http://github.com/strongloop/loopback-connector-postgres) - In Development
- - [Redis](http://github.com/strongloop/loopback-connector-redis) - In Development
- - [CouchDB](http://github.com/strongloop/loopback-connector-couch) - In Development
- - [Firebird](http://github.com/strongloop/loopback-connector-firebird) - In Development
-
-**Other Connectors**
-
- - [REST](http://github.com/strongloop/loopback-connector-rest)
- - [Email](#email-model)
- - [JSON RPC](http://github.com/strongloop/loopback-connector-jsonrpc) - In Development
- - [SOAP](http://github.com/strongloop/loopback-connector-soap) - In Development
- - [Push Notifications](https://github.com/strongloop/loopback-push-notification) - In Development
- - [File Storage](https://github.com/strongloop/loopback-storage-service) - In Development
-
-**Installing Connectors**
-
-Include the connector in your package.json dependencies and run `npm install`.
-
-```js
-{
- "dependencies": {
- "loopback-connector-oracle": "latest"
- }
-}
-```
-
-##### Memory Connector
-
-The built-in memory connector allows you to test your application without connecting to an actual persistent data source, such as a database. Although the memory connector is very well tested it is not recommended to be used in production. Creating a data source using the memory connector is very simple.
-
-```js
-// use the built in memory function
-// to create a memory data source
-var memory = loopback.memory();
-
-// or create it using the standard
-// data source creation api
-var memory = loopback.createDataSource({
- connector: loopback.Memory
-});
-
-// create a model using the
-// memory data source
-var properties = {
- name: String,
- price: Number
-};
-
-var Product = memory.createModel('product', properties);
-
-Product.create([
- {name: 'apple', price: 0.79},
- {name: 'pear', price: 1.29},
- {name: 'orange', price: 0.59},
-], count);
-
-function count() {
- Product.count(console.log); // 3
-}
-```
-
-**CRUD / Query**
-
-The memory connector supports all the standard [query and crud operations](#crud-and-query-mixins) to allow you to test your models against an in memory data source.
-
-**GeoPoint Filtering**
-
-The memory connector also supports geo-filtering when using the `find()` operation with an attached model. See [GeoPoint](#geopoint) for more information on geo-filtering.
-
-### GeoPoint
-
-Use the `GeoPoint` class.
-
-```js
-var GeoPoint = require('loopback').GeoPoint;
-```
-
-Embed a latitude / longitude point in a [Model](#model).
-
-```js
-var CoffeeShop = loopback.createModel('coffee-shop', {
- location: 'GeoPoint'
-});
-```
-
-Loopback Model's with a GeoPoint property and an attached DataSource may be queried using geo spatial filters and sorting.
-
-Find the 3 nearest coffee shops.
-
-```js
-CoffeeShop.attachTo(oracle);
-var here = new GeoPoint({lat: 10.32424, lng: 5.84978});
-CoffeeShop.find({where: {location: {near: here}}, limit:3}, function(err, nearbyShops) {
- console.info(nearbyShops); // [CoffeeShop, ...]
-});
-```
-
-#### geoPoint.distanceTo(geoPoint, options)
-
-Get the distance to another `GeoPoint`.
-
-```js
-var here = new GeoPoint({lat: 10, lng: 10});
-var there = new GeoPoint({lat: 5, lng: 5});
-console.log(here.distanceTo(there, {type: 'miles'})); // 438
-```
-
-#### GeoPoint.distanceBetween(a, b, options)
-
-Get the distance between two points.
-
-```js
-GeoPoint.distanceBetween(here, there, {type: 'miles'}) // 438
-```
-
-#### Distance Types
-
-**Note:** all distance methods use `miles` by default.
-
- - `miles`
- - `radians`
- - `kilometers`
- - `meters`
- - `miles`
- - `feet`
- - `degrees`
-
-#### geoPoint.lat
-
-The latitude point in degrees. Range: -90 to 90.
-
-#### geoPoint.lng
-
-The longitude point in degrees. Range: -180 to 180.
+ * [App](api-app.md)
+ * [Model](api-model.md)
+ * [Remote methods and hooks](api-model-remote.md)
+ * [DataSource](api-datasource.md)
+ * [GeoPoint](api-geopoint.md)
diff --git a/docs/rest.md b/docs/rest.md
index cc141525a..8bbaa4b3c 100644
--- a/docs/rest.md
+++ b/docs/rest.md
@@ -1,125 +1,25 @@
-## REST API
-
-The REST API allows clients to interact with the LoopBack models using HTTP.
-The clients can be a web browser, a JavaScript program, a mobile SDK, a curl
-script, or anything that can act as an HTTP client.
-
-LoopBack automatically binds a model to a list of HTTP endpoints that provide
-REST APIs for model instance data manipulations (CRUD) and other remote
-operations.
-
-We'll use a simple model called `Location` (locations for rental) to illustrate
-what REST APIs are exposed by LoopBack.
-
-By default, the REST APIs are mounted to `/`, for
-example, `/locations`, to the base URL such as http://localhost:3000/.
-
-### CRUD remote methods
-
-For a model backed by a data source that supports CRUD operations, you'll see
-the following endpoints:
-
-- Model.create: POST /locations
-- Model.upsert: PUT /locations
-- Model.exists: GET /locations/:id/exists
-- Model.findById: GET /locations/:id
-- Model.find: GET /locations
-- Model.findOne: GET /locations/findOne
-- Model.deleteById: DELETE /locations/:id
-- Model.count: GET /locations/count
-- Model.prototype.updateAttributes: PUT /locations/:id
-
-### Custom remote methods
-
-To expose a JavaScript method as REST API, we can simply describe the method as
-follows:
-
- loopback.remoteMethod(
- Location.nearby,
- {
- description: 'Find nearby locations around the geo point',
- accepts: [
- {arg: 'here', type: 'GeoPoint', required: true, description: 'geo location (lat & lng)'},
- {arg: 'page', type: 'Number', description: 'number of pages (page size=10)'},
- {arg: 'max', type: 'Number', description: 'max distance in miles'}
- ],
- returns: {arg: 'locations', root: true},
- http: {verb: 'POST', path: '/nearby'}
- }
- );
-
-The remoting is defined using the following properties:
-
-- description: Description of the REST API
-- accepts: An array of parameters, each parameter has a name, a type, and an
-optional description
-- returns: Description of the return value
-- http: Binding to the HTTP endpoint, including the verb and path
-
-### Request Format
-
-For POST and PUT requests, the request body must be JSON, with the Content-Type
-header set to application/json.
-
-#### Encode the JSON object as query string
-
-LoopBack uses the syntax from [node-querystring](https://github.com/visionmedia/node-querystring)
-to encode JSON objects or arrays as query string. For example,
-
- user[name][first]=John&user[email]=callback@strongloop.com
- ==>
- { user: { name: { first: 'John' }, email: 'callback@strongloop.com' } }
-
- user[names][]=John&user[names][]=Mary&user[email]=callback@strongloop.com
- ==>
- { user: { names: ['John', 'Mary'], email: 'callback@strongloop.com' }}
-
- items=a&items=b
- ==> { items: ['a', 'b'] }
-
-For more examples, please check out [node-querystring](https://github.com/visionmedia/node-querystring/blob/master/test/parse.js)
-
-
-### Response Format
-
-The response format for all requests is a JSON object or array if present. Some
-responses have an empty body.
-
-Whether a request succeeded is indicated by the HTTP status code. A 2xx status
-code indicates success, whereas a 4xx status code indicates request related
-issues. 5xx status code reports server side problems.
-
-The response for an error is in the following format:
-
- {
- "error": {
- "message": "could not find a model with id 1",
- "stack": "Error: could not find a model with id 1\n ...",
- "statusCode": 404
- }
- }
-
-###Generated APIs
-
-
-###create
+##create
Create a new instance of the model and persist it into the data source
-####Definition
+###Definition
POST /locations
-####Arguments
+###Arguments
* **data** The model instance data
-####Example Request
+###Example
+
+Request:
+
curl -X POST -H "Content-Type:application/json" \
-d '{"name": "L1", "street": "107 S B St", "city": "San Mateo", "zipcode": "94401"}' \
http://localhost:3000/locations
-####Example Response
+Response:
+
{
"id": "96",
"street": "107 S B St",
@@ -132,39 +32,31 @@ Create a new instance of the model and persist it into the data source
}
}
-####Potential Errors
-* None
-
+### Errors
-###upsert
+None
+##upsert
Update an existing model instance or insert a new one into the data source
-####Definition
-
+###Definition
PUT /locations
-####Arguments
+###Arguments
* **data** The model instance data
+###Examples
-####Example Request
+Request - insert:
-#####Insert
curl -X PUT -H "Content-Type:application/json" \
-d '{"name": "L1", "street": "107 S B St", "city": "San Mateo", "zipcode": "94401"}' \
http://localhost:3000/locations
-#####Update
- curl -X PUT -H "Content-Type:applicatin/json" \
- -d '{"id": "98", "name": "L4", "street": "107 S B St", "city": "San Mateo", \
- "zipcode": "94401"}' http://localhost:3000/locations
-
-####Example Response
+Response:
-#####Insert
{
"id": "98",
"street": "107 S B St",
@@ -176,8 +68,15 @@ Update an existing model instance or insert a new one into the data source
"lng": -122.3240212
}
}
+
+Request - update:
+
+ curl -X PUT -H "Content-Type:applicatin/json" \
+ -d '{"id": "98", "name": "L4", "street": "107 S B St", "city": "San Mateo", \
+ "zipcode": "94401"}' http://localhost:3000/locations
+
+Response:
-#####Update
{
"id": "98",
"street": "107 S B St",
@@ -187,55 +86,57 @@ Update an existing model instance or insert a new one into the data source
}
-####Potential Errors
-* None
-
+### Errors
-###exists
+None
+##exists
-Check whether a model instance exists by id in the data source
-
-####Definition
+Check whether a model instance exists by ID in the data source.
+###Definition
GET /locations/exists
-####Arguments
+###Arguments
+
* **id** The model id
+###Example
+
+Request:
-####Example Request
curl http://localhost:3000/locations/88/exists
-####Example Response
+Response:
{
"exists": true
}
-####Potential Errors
-* None
+### Errors
+None
-###findById
+##findById
+Find a model instance by ID from the data source.
-Find a model instance by id from the data source
-
-####Definition
-
+###Definition
GET /locations/{id}
-####Arguments
+###Arguments
+
* **id** The model id
+###Example
+
+Request:
-####Example Request
curl http://localhost:3000/locations/88
-####Example Response
+Response:
{
"id": "88",
@@ -249,21 +150,20 @@ Find a model instance by id from the data source
}
}
-####Potential Errors
-* None
-
+### Errors
-###find
+None
+##find
-Find all instances of the model matched by filter from the data source
-
-####Definition
+Find all instances of the model matched by filter from the data source.
+###Definition
GET /locations
####Arguments
+
* **filter** The filter that defines where, order, fields, skip, and limit
- **where** `Object` { key: val, key2: {gt: 'val2'}} The search criteria
@@ -315,17 +215,21 @@ For example,
- '/locations?filter[where][geo][near]=153.536,-28.1&filter[limit]=3': The 3 closest locations to a given geo point
-####Example Request
+###Example
+
+Request:
+
+Find without filter:
-#####Find without filter
curl http://localhost:3000/locations
-#####Find with a filter
+Find with a filter:
+
curl http://localhost:3000/locations?filter%5Blimit%5D=2
**Note**: For curl, `[` needs to be encoded as `%5B`, and `]` as `%5D`.
-####Example Response
+Response:
[
{
@@ -352,30 +256,30 @@ For example,
}
]
-####Potential Errors
-* None
-
+### Errors
-###findOne
+None
+##findOne
-Find first instance of the model matched by filter from the data source
-
-
-####Definition
+Find first instance of the model matched by filter from the data source.
+###Definition
GET /locations/findOne
-####Arguments
+###Arguments
+
* **filter** The filter that defines where, order, fields, skip, and limit. It's
same as find's filter argument. Please see [find](#find) for more details.
+###Example
+
+Request:
-####Example Request
curl http://localhost:3000/locations/findOne?filter%5Bwhere%5D%5Bcity%5D=Scottsdale
-####Example Response
+Response:
{
"id": "87",
@@ -389,86 +293,89 @@ same as find's filter argument. Please see [find](#find) for more details.
}
}
-####Potential Errors
-* None
-
+### Errors
-###deleteById
+None
+##deleteById
Delete a model instance by id from the data source
-####Definition
-
+###Definition
DELETE /locations/{id}
-####Arguments
+###Arguments
+
* **id** The model id
+###Example
-####Example Request
- curl -X DELETE http://localhost:3000/locations/88
+Request:
-####Example Response
+ curl -X DELETE http://localhost:3000/locations/88
+Response:
-####Potential Errors
-* None
+Example TBD.
+### Errors
-###count
+None
+##count
Count instances of the model matched by where from the data source
-####Definition
-
+###Definition
GET /locations/count
-####Arguments
+###Arguments
+
* **where** The criteria to match model instances
+###Example
-####Example Request
+Request - count without "where" filter
-#####Count without where
curl http://localhost:3000/locations/count
-#####Count with a where filter
+Request - count with a "where" filter
+
curl http://localhost:3000/locations/count?where%5bcity%5d=Burlingame
-####Example Response
+Response:
{
count: 6
}
-####Potential Errors
-* None
-
+### Errors
-###nearby
+None
+##nearby
-Find nearby locations around the geo point
-
-####Definition
+Find nearby locations around the geo point.
+###Definition
GET /locations/nearby
-####Arguments
+###Arguments
+
* **here** geo location object with `lat` and `lng` properties
* **page** number of pages (page size=10)
* **max** max distance in miles
+###Example
+
+Request:
-####Example Request
curl http://localhost:3000/locations/nearby?here%5Blat%5D=37.587409&here%5Blng%5D=-122.338225
-####Example Response
+Response:
[
{
@@ -495,30 +402,32 @@ Find nearby locations around the geo point
}
]
-####Potential Errors
-* None
-
+### Errors
-###updateAttributes
+None
+##updateAttributes
Update attributes for a model instance and persist it into the data source
-####Definition
-
+###Definition
PUT /locations/{id}
-####Arguments
+###Arguments
+
* **data** An object containing property name/value pairs
* **id** The model id
+###Example
+
+Request:
-####Example Request
curl -X PUT -H "Content-Type:application/json" -d '{"name": "L2"}' \
http://localhost:3000/locations/88
-####Example Response
+Response:
+
{
"id": "88",
"street": "390 Lang Road",
@@ -532,29 +441,30 @@ Update attributes for a model instance and persist it into the data source
"state": "CA"
}
-####Potential Errors
-* 404 No instance found for the given id
-
+### Errors
-###getAssociatedModel
+* 404 No instance found for the given id
+##getAssociatedModel
Follow the relations from one model (`location`) to another one (`inventory`) to
get instances of the associated model.
-####Definition
-
+###Definition
GET /locations/{id}/inventory
-####Arguments
+###Arguments
+
* **id** The id for the location model
+###Example
+
+Request:
-####Example Request
curl http://localhost:3000/locations/88/inventory
-####Example Response
+Response:
[
{
@@ -571,8 +481,9 @@ get instances of the associated model.
}
]
-####Potential Errors
-* None
+### Errors
+
+None