Merge branch 'release/1.2.5' into production

This commit is contained in:
Ritchie Martori 2013-12-04 11:41:00 -08:00
commit e2cd20d73f
8 changed files with 31 additions and 129 deletions

2
.jshintignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
support/nodeunit

121
README.md
View File

@ -4,124 +4,7 @@ LoopBack DataSource Juggler is an ORM that provides a common set of interfaces
for interacting with databases, REST APIs, and other data sources. It was
initially forked from [JugglingDB](https://github.com/1602/jugglingdb).
## Overview
LoopBack DataSource Juggler consists of the following components:
* LoopBack Definition Language
* DataSource
* Connector
![loopback-datasource-juggler-overview](docs/overview.png "LoopBack Diagram")
## LoopBack Definition Language
To define model dataSource have single method `dataSource.define`. It accepts
three arguments:
* **model name**:
String name in camel-case with first upper-case letter. This name will be
used later to access model.
* **properties**:
Object with property type definitions. Key is property name, value is type
definition. Type definition can be function representing type of property
(String, Number, Date, Boolean), or object with {type: String|Number|...,
index: true|false} format.
* **settings**:
Object with model-wide settings such as `tableName` or so.
Examples of model definition:
var User = dataSource.define('User', {
email: String,
password: String,
birthDate: Date,
activated: Boolean
});
var User = dataSource.define('User', {
email: { type: String, limit: 150, index: true },
password: { type: String, limit: 50 },
birthDate: Date,
registrationDate: {
type: Date,
default: function () { return new Date }
},
activated: { type: Boolean, default: false }
}, {
tableName: 'users'
});
## DataSource
DataSource is a factory for model classes. DataSource connected with specific
database or other backend system using connector.
All model classes within single datasource shares same connector type and one
database connection. But it's possible to use more than one datasource to
connect with different databases.
### Creating dataSource
`DataSource` constructor available on `loopback-datasource-juggler` module:
var DataSource = require('loopback-datasource-juggler').DataSource;
DataSource constructor accepts two arguments. First argument is connector. It
could be a connector name or connector package:
var dataSourceByConnectorName = new DataSource('memory');
var dataSourceByConnectorModule = new DataSource(require('redis'));
### Settings
Second argument is optional settings. Settings object format and defaults
depends on specific connector, but common fields are:
* `host`: Database host
* `port`: Database port
* `username`: Username to connect to database
* `password`: Password to connect to database
* `database`: Database name
* `debug`: Turn on verbose mode to debug db queries and lifecycle
For connector-specific settings refer to connector's readme file.
## LoopBack Connectors
| Type | Package Name |
| --------- |:--------------------------------------------------------------------------------------:|
| MongoDB | [loopback-connector-mongodb](https://github.com/strongloop/loopback-connector-mongodb) |
| Oracle | [loopback-connector-oracle](https://github.com/strongloop/loopback-connector-oracle) |
| MySQL | [loopback-connector-mysql](https://github.com/strongloop/loopback-connector-mysql) |
LoopBack connectors provide access to backend systems including databases,
REST APIs and other services. Connectors are not used directly by application
code. We create a DataSource to interact with the connector.
For example,
var DataSource = require('loopback-datasource-juggler').DataSource;
var oracleConnector = require('loopback-connector-oracle');
var ds = new DataSource(oracleConnector, {
host : '127.0.0.1',
database : 'XE',
username : 'strongloop',
password : 'password',
debug : true
});
The connector argument passed the DataSource constructor can be one of the
following:
* The connector module from `require(connectorName)`
* The full name of the connector module, such as 'loopback-connector-oracle'
* The short name of the connector module, such as 'oracle', which will be
converted to 'loopback-connector-<shortName>'
* A local module under ./connectors/<connectorName> folder
For full documentation, see [StrongLoop Suite Documentation](http://docs.strongloop.com/display/DOC/Data+Source+Juggler).
## Installation
@ -131,6 +14,6 @@ Also install the appropriated connector, for example for mongodb:
npm install loopback-connector-mongodb
check following list of available connectors
See [StrongLoop Suite Documentation](http://docs.strongloop.com/) for up-to-date list of connectors supported.

View File

@ -4,6 +4,7 @@ exports.ModelBuilder = exports.LDL = require('./lib/model-builder.js').ModelBuil
exports.DataSource = exports.Schema = require('./lib/datasource.js').DataSource;
exports.ModelBaseClass = require('./lib/model.js');
exports.Connector = require('./lib/connector.js');
exports.ValidationError = require('./lib/validations.js').ValidationError;
var baseSQL = './lib/sql';

View File

@ -331,9 +331,20 @@ setRemoting(DataAccessObject.findById, {
description: 'Find a model instance by id from the data source',
accepts: {arg: 'id', type: 'any', description: 'Model id', required: true},
returns: {arg: 'data', type: 'any', root: true},
http: {verb: 'get', path: '/:id'}
http: {verb: 'get', path: '/:id'},
rest: {after: convertNullToNotFoundError}
});
function convertNullToNotFoundError(ctx, cb) {
if (ctx.result !== null) return cb();
var modelName = ctx.method.sharedClass.name;
var id = ctx.getArgByName('id');
var msg = 'Unkown "' + modelName + '" id "' + id + '".';
var error = new Error(msg);
error.statusCode = error.status = 404;
cb(error);
}
// alias function for backwards compat.
DataAccessObject.all = function () {

View File

@ -599,12 +599,16 @@ function ValidationError(obj) {
if (!(this instanceof ValidationError)) return new ValidationError(obj);
this.name = 'ValidationError';
this.message = 'Validation error';
this.statusCode = 400;
this.codes = obj.errors && obj.errors.codes;
this.context = obj && obj.constructor && obj.constructor.modelName;
this.message = 'The Model instance is not valid. ' +
'See `details` property of the error object for more info.';
this.statusCode = 422;
this.details = {
context: obj && obj.constructor && obj.constructor.modelName,
codes: obj.errors && obj.errors.codes,
messages: obj.errors
};
Error.call(this);
Error.captureStackTrace(this, this.constructor);
}

View File

@ -1,6 +1,6 @@
{
"name": "loopback-datasource-juggler",
"version": "1.2.4",
"version": "1.2.5",
"description": "LoopBack DataSoure Juggler",
"keywords": [
"StrongLoop",

View File

@ -2,6 +2,7 @@
var should = require('./init.js');
var db, Person;
var ValidationError = require('..').ValidationError;
describe('manipulation', function() {
@ -173,7 +174,7 @@ describe('manipulation', function() {
p.save({
'throws': true
});
}).should.throw('Validation error');
}).should.throw(ValidationError);
});
});

View File

@ -2,7 +2,7 @@
var should = require('./init.js');
var j = require('../'), db, User;
var ValidationError = require('../lib/validations.js').ValidationError;
var ValidationError = j.ValidationError;
function getValidAttributes() {
return {
@ -98,7 +98,7 @@ describe('validations', function() {
User.validatesPresenceOf('name');
User.create(function(e, u) {
should.exist(e);
e.codes.name.should.eql(['presence']);
e.details.codes.name.should.eql(['presence']);
done();
});
});