params.json 32.9 KB
{"name":"Object Relational Mapping","tagline":"For NodeJS","body":"## Install [![Build Status](]( [![](]( [![](](\r\n\r\n```sh\r\nnpm install orm\r\n```\r\n\r\n## Node.js Version Support\r\n\r\nTests are done using [Travis CI]( for node versions 0.4.x, 0.6.x, 0.8.x and 0.10.x. If you want you can run\r\ntests locally.\r\n\r\n```sh\r\nmake\r\n```\r\n\r\n## DBMS Support\r\n\r\n- MySQL\r\n- PostgreSQL\r\n- Amazon Redshift\r\n- SQLite\r\n\r\n## Features\r\n\r\n- Create Models, sync, drop, bulk create, get, find, remove, count, aggregated functions\r\n- Create Model associations, find, check, create and remove\r\n- Define custom validations (several builtin validations, check instance properties before saving)\r\n- Model instance caching and integrity (table rows fetched twice are the same object, changes to one change all)\r\n- Plugins: [MySQL FTS]( , [Pagination]( , [Transaction](\r\n\r\n## Introduction\r\n\r\nThis is a node.js object relational mapping module.\r\n\r\nAn example:\r\n\r\n```js\r\nvar orm = require(\"orm\");\r\n\r\norm.connect(\"mysql://username:password@host/database\", function (err, db) {\r\n  if (err) throw err;\r\n\r\n\tvar Person = db.define(\"person\", {\r\n\t\tname      : String,\r\n\t\tsurname   : String,\r\n\t\tage       : Number,\r\n\t\tmale      : Boolean,\r\n\t\tcontinent : [ \"Europe\", \"America\", \"Asia\", \"Africa\", \"Australia\", \"Antartica\" ], // ENUM type\r\n\t\tphoto     : Buffer, // BLOB/BINARY\r\n\t\tdata      : Object // JSON encoded\r\n\t}, {\r\n\t\tmethods: {\r\n\t\t\tfullName: function () {\r\n\t\t\t\treturn + ' ' + this.surname;\r\n\t\t\t}\r\n\t\t},\r\n\t\tvalidations: {\r\n\t\t\tage: orm.validators.rangeNumber(18, undefined, \"under-age\")\r\n\t\t}\r\n\t});\r\n\r\n\tPerson.find({ surname: \"Doe\" }, function (err, people) {\r\n\t\t// SQL: \"SELECT * FROM person WHERE surname = 'Doe'\"\r\n\r\n\t\tconsole.log(\"People found: %d\", people.length);\r\n\t\tconsole.log(\"First person: %s, age %d\", people[0].fullName(), people[0].age);\r\n\r\n\t\tpeople[0].age = 16;\r\n\t\tpeople[0].save(function (err) {\r\n\t\t\t// err.msg = \"under-age\";\r\n\t\t});\r\n\t});\r\n});\r\n```\r\n\r\n## Express\r\n\r\nIf you're using Express, you might want to use the simple middleware to integrate more easily.\r\n\r\n```js\r\nvar express = require('express');\r\nvar orm = require('orm');\r\nvar app = express();\r\n\r\napp.use(\"mysql://username:password@host/database\", {\r\n\tdefine: function (db, models) {\r\n\t\tmodels.person = db.define(\"person\", { ... });\r\n\t}\r\n}));\r\napp.listen(80);\r\n\r\napp.get(\"/\", function (req, res) {\r\n\t// req.models is a reference to models used above in define()\r\n\treq.models.person.find(...);\r\n});\r\n```\r\n\r\nYou can call `` more than once to have multiple database connections. Models defined across connections\r\nwill be joined together in `req.models`. **Don't forget to use it before `app.use(app.router)`, preferably right after your\r\nassets public folder(s).**\r\n\r\n## Settings\r\n\r\nSettings are used to store key value pairs. A settings object is stored on the global orm object and on each database connection.\r\n\r\n```js\r\nvar orm = require(\"orm\");\r\n\r\norm.settings.set(\"some.deep.value\", 123);\r\n\r\norm.connect(\"....\", function (err, db) {\r\n\t// db.settings is a snapshot of the settings at the moment\r\n\t// of orm.connect(). changes to it don't affect orm.settings\r\n\r\n\tconsole.log(db.settings.get(\"some.deep.value\")); // 123\r\n\tconsole.log(db.settings.get(\"some.deep\"));       // { value: 123 }\r\n});\r\n```\r\n\r\n## Connecting\r\n\r\nFirst, add the correct driver to your `package.json`:\r\n\r\n driver                | dependency\r\n:----------------------|:---------------------------\r\n mysql                 | `\"mysql\" : \"2.0.0-alpha7\"`\r\n postgres<br/>redshift | `\"pg\": \"~1.0.0\"`\r\n sqlite                | `\"sqlite3\" : \"2.1.7\"`\r\n\r\nThese are the versions tested. Use others (older or newer) at your own risk.\r\n\r\n### Options\r\n\r\nYou can pass in connection options either as a string:\r\n\r\n```js\r\nvar orm = require(\"orm\");\r\n\r\norm.connect(\"mysql://username:password@host/database?pool=true\", function (err, db) {\r\n\t// ...\r\n});\r\n```\r\n\r\n**Note:** `pool` is only supported by mysql & postgres. When 'pool' is set to true, your database connections are cached so that connections can be reused, optimizing performance.\r\n\r\n**Note:** `strdates` is only supported by sqlite. When true, date fields are saved as strings, compatible with django\r\n\r\nOr as an object:\r\n\r\n```js\r\nvar opts = {\r\n  database : \"dbname\",\r\n  protocol : \"[mysql|postgres|redshift|sqlite]\",\r\n  host     : \"\",\r\n  port     : 3306,         // optional, defaults to database default\r\n  user     : \"..\",\r\n  password : \"..\",\r\n  query    : {\r\n    pool     : true|false,   // optional, false by default\r\n    debug    : true|false,   // optional, false by default\r\n    strdates : true|false    // optional, false by default\r\n  }\r\n};\r\norm.connect(opts, function (err, db) {\r\n\t// ...\r\n});\r\n```\r\n\r\nYou can also avoid passing a callback and just listen for the connect event:\r\n\r\n```js\r\nvar orm = require(\"orm\");\r\nvar db  = orm.connect(\"mysql://username:password@host/database\");\r\n\r\ndb.on(\"connect\", function (err, db) {\r\n\t// ...\r\n});\r\n```\r\n\r\n## Models\r\n\r\nA Model is an abstraction over one or more database tables. Models support associations (more below). The name of the model is assumed to match the table name.\r\n\r\nModels support behaviours for accessing and manipulating table data.\r\n\r\n## Defining Models\r\n\r\nCall `define` on the database connection to setup a model. The name of the table and model is used as an identifier for the model on the database connection, so you can easily access the model later using the connection.\r\n\r\n```js\r\nvar Person = db.define('person', {        // 'person' will be the table in the database as well as the model id\r\n\t// properties\r\n\tname    : String,                     // you can use native objects to define the property type\r\n\tsurname : { type: \"text\", size: 50 }  // or you can be specific and define aditional options\r\n}, {\r\n\t// options (optional)\r\n});\r\n```\r\n\r\n### Properties\r\n\r\n#### Types\r\n\r\n\r\n Native   | String     | Native   | String\r\n :--------|:-----------|:---------|:---------\r\n String   | 'text'     | Date     | 'date '\r\n Number   | 'number'   | Object   | 'object'\r\n Boolean  | 'boolean'  | Buffer   | 'binary'\r\n          |            |  ---     | 'enum'\r\n\r\n#### Options\r\n\r\n##### [all types]\r\n* `required`: true marks the column as `NOT NULL`, false (default)\r\n* `defaultValue`: sets the default value for the field\r\n\r\n##### string\r\n* `size`: max length of the string\r\n\r\n##### number\r\n* `rational`: true (default) creates a FLOAT/REAL, false an INTEGER\r\n* `size`: byte size of number, default is 4. Note that 8 byte numbers [have limitations](\r\n* `unsigned`: true to make INTEGER unsigned, default is false\r\n\r\n##### date\r\n* `time`: true (default) creates a DATETIME/TIMESTAMP, false a DATE\r\n\r\nNote that these may vary accross drivers.\r\n\r\n### Instance Methods\r\n\r\nAre passed in during model definition.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n    name    : String,\r\n    surname : String\r\n}, {\r\n    methods: {\r\n        fullName: function () {\r\n            return + ' ' + this.surname;\r\n        }\r\n    }\r\n});\r\n\r\nPerson.get(4, function(err, person) {\r\n    console.log( person.fullName() );\r\n})\r\n```\r\n\r\n### Model Methods\r\n\r\nAre defined directly on the model.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n    name    : String,\r\n    height  : { type: 'number', rational: false }\r\n});\r\nPerson.tallerThan = function(height, callback) {\r\n    this.find({ height: }, callback);\r\n};\r\n\r\nPerson.tallerThan( 192, function(err, tallPeople) { ... } );\r\n```\r\n\r\n\r\n## Loading Models\r\n\r\nModels can be in separate modules. Simply ensure that the module holding the models uses module.exports to publish a function that accepts the database connection, then load your models however you like.\r\n\r\nNote - using this technique you can have cascading loads.\r\n\r\n```js\r\n// your main file (after connecting)\r\ndb.load(\"./models\", function (err) {\r\n    // loaded!\r\n    var Person = db.models.person;\r\n    var Pet    =;\r\n});\r\n\r\n// models.js\r\nmodule.exports = function (db, cb) {\r\n    db.load(\"./models-extra\", function (err) {\r\n        if (err) {\r\n            return cb(err);\r\n        }\r\n\r\n        db.define('person', {\r\n            name : String\r\n        });\r\n\r\n        return cb();\r\n    });\r\n};\r\n\r\n// models-extra.js\r\nmodule.exports = function (db, cb) {\r\n    db.define('pet', {\r\n        name : String\r\n    });\r\n\r\n    return cb();\r\n};\r\n```\r\n\r\n## Synchronizing Models\r\n\r\nModels can create their underlying tables in the database. You may call Model.sync() on each Model to create the underlying table or you can call db.sync() at a connection level to create all tables for all models.\r\n\r\n```js\r\n// db.sync() can also be used\r\nPerson.sync(function (err) {\r\n\t!err && console.log(\"done!\");\r\n});\r\n```\r\n\r\n## Dropping Models\r\n\r\nIf you want to drop a Model and remove all tables you can use the `.drop()` method.\r\n\r\n```js\r\nPerson.drop(function (err) {\r\n\t!err && console.log(\"person model no longer exists!\");\r\n});\r\n```\r\n\r\n## Advanced Options\r\n\r\nORM2 allows you some advanced tweaks on your Model definitions. You can configure these via settings or in the call to `define` when you setup the Model.\r\n\r\nFor example, each Model instance has a unique ID in the database. This table column is\r\nby default \"id\" but you can change it.\r\n\r\n```js\r\nvar Person = db.define(\"person\", {\r\n\tname : String\r\n}, {\r\n\tid   : \"person_id\"\r\n});\r\n\r\n// or just do it globally..\r\ndb.settings.set(\"properties.primary_key\", \"UID\");\r\n\r\n// ..and then define your Models\r\nvar Pet = db.define(\"pet\", {\r\n\tname : String\r\n});\r\n```\r\n\r\n**Pet** model will have 2 columns, an `UID` and a `name`.\r\n\r\nOther options:\r\n\r\n- `cache` : (default: `true`) Set it to `false` to disable Instance cache ([Singletons](#singleton)) or set a timeout value (in seconds);\r\n- `autoSave` : (default: `false`) Set it to `true` to save an Instance right after changing any property;\r\n- `autoFetch` : (default: `false`) Set it to `true` to fetch associations when fetching an instance from the database;\r\n- `autoFetchLimit` : (default: `1`) If `autoFetch` is enabled this defines how many hoops (associations of associations)\r\n  you want it to automatically fetch.\r\n\r\n## Hooks\r\n\r\nIf you want to listen for a type of event than occurs in instances of a Model, you can attach a function that\r\nwill be called when that event happens.\r\n\r\nCurrently the following events are supported:\r\n\r\n- `afterLoad` : (no parameters) Right after loading and preparing an instance to be used;\r\n- `afterAutoFetch` : (no parameters) Right after auto-fetching associations (if any), it will trigger regardless of having associations or not;\r\n- `beforeSave` : (no parameters) Right before trying to save;\r\n- `afterSave` : (bool success) Right after saving;\r\n- `beforeCreate` : (no parameters) Right before trying to save a new instance (prior to `beforeSave`);\r\n- `afterCreate` : (bool success) Right after saving a new instance;\r\n- `beforeRemove` : (no parameters) Right before trying to remove an instance;\r\n- `afterRemove` : (bool success) Right after removing an instance;\r\n- `beforeValidation` : (no parameters) Before all validations and prior to `beforeCreate` and `beforeSave`;\r\n\r\nAll hook function are called with `this` as the instance so you can access anything you want related to it.\r\n\r\nFor all `before*` hooks, you can add an additional parameter to the hook function. This parameter will be a function that\r\nmust be called to tell if the hook allows the execution to continue or to break. You might be familiar with this workflow\r\nalready from Express. Here's an example:\r\n\r\n```js\r\nvar Person = db.define(\"person\", {\r\n\tname    : String,\r\n\tsurname : String\r\n}, {\r\n\thooks: {\r\n\t\tbeforeCreate: function (next) {\r\n\t\t\tif (this.surname == \"Doe\") {\r\n\t\t\t\treturn next(new Error(\"No Does allowed\"));\r\n\t\t\t}\r\n\t\t\treturn next();\r\n\t\t}\r\n\t}\r\n});\r\n```\r\n\r\nThis workflow allows you to make asynchronous work before calling `next`.\r\n\r\n## Finding Items\r\n\r\n### Model.get(id, [ options ], cb)\r\n\r\nTo get a specific element from the database use `Model.get`.\r\n\r\n```js\r\nPerson.get(123, function (err, person) {\r\n\t// finds person with id = 123\r\n});\r\n```\r\n\r\n### Model.find([ conditions ] [, options ] [, limit ] [, order ] [, cb ])\r\n\r\nFinding one or more elements has more options, each one can be given in no specific parameter order. Only `options` has to be after `conditions` (even if it's an empty object).\r\n\r\n```js\r\nPerson.find({ name: \"John\", surname: \"Doe\" }, 3, function (err, people) {\r\n\t// finds people with name='John' AND surname='Doe' and returns the first 3\r\n});\r\n```\r\n\r\nIf you need to sort the results because you're limiting or just because you want them sorted do:\r\n\r\n```js\r\nPerson.find({ surname: \"Doe\" }, \"name\", function (err, people) {\r\n\t// finds people with surname='Doe' and returns sorted by name ascending\r\n});\r\nPerson.find({ surname: \"Doe\" }, [ \"name\", \"Z\" ], function (err, people) {\r\n\t// finds people with surname='Doe' and returns sorted by name descending\r\n\t// ('Z' means DESC; 'A' means ASC - default)\r\n});\r\n```\r\n\r\nThere are more options that you can pass to find something. These options are passed in a second object:\r\n\r\n```js\r\nPerson.find({ surname: \"Doe\" }, { offset: 2 }, function (err, people) {\r\n\t// finds people with surname='Doe', skips the first 2 and returns the others\r\n});\r\n```\r\n\r\n### Model.count([ conditions, ] cb)\r\n\r\nIf you just want to count the number of items that match a condition you can just use `.count()` instead of finding all\r\nof them and counting. This will actually tell the database server to do a count (it won't be done in the node process itself).\r\n\r\n```js\r\nPerson.count({ surname: \"Doe\" }, function (err, count) {\r\n\tconsole.log(\"We have %d Does in our db\", count);\r\n});\r\n```\r\n\r\n### Model.exists([ conditions, ] cb)\r\n\r\nSimilar to `.count()`, this method just checks if the count is greater than zero or not.\r\n\r\n```js\r\nPerson.exists({ surname: \"Doe\" }, function (err, exists) {\r\n\tconsole.log(\"We %s Does in our db\", exists ? \"have\" : \"don't have\");\r\n});\r\n```\r\n\r\n### Aggregating Functions\r\n\r\nIf you need to get some aggregated values from a Model, you can use `Model.aggregate()`. Here's an example to better\r\nillustrate:\r\n\r\n```js\r\nPerson.aggregate({ surname: \"Doe\" }).min(\"age\").max(\"age\").get(function (err, min, max) {\r\n\tconsole.log(\"The youngest Doe guy has %d years, while the oldest is %d\", min, max);\r\n});\r\n```\r\n\r\nAn `Array` of properties can be passed to select only a few properties. An `Object` is also accepted to define conditions.\r\n\r\nHere's an example to illustrate how to use `.groupBy()`:\r\n\r\n```js\r\n//The same as \"select avg(weight), age from person where country='someCountry' group by age;\"\r\nPerson.aggregate([\"age\"], { country: \"someCountry\" }).avg(\"weight\").groupBy(\"age\").get(function (err, stats) {\r\n    // stats is an Array, each item should have 'age' and 'avg_weight'\r\n});\r\n```\r\n\r\n### Base `.aggregate()` methods\r\n\r\n- `.limit()`: you can pass a number as a limit, or two numbers as offset and limit respectively\r\n- `.order()`: same as `Model.find().order()`\r\n\r\n### Additional `.aggregate()` methods\r\n\r\n- `min`\r\n- `max`\r\n- `avg`\r\n- `sum`\r\n- `count` (there's a shortcut to this - `Model.count`)\r\n\r\nThere are more aggregate functions depending on the driver (Math functions for example).\r\n\r\n#### Chaining\r\n\r\nIf you prefer less complicated syntax you can chain `.find()` by not giving a callback parameter.\r\n\r\n```js\r\nPerson.find({ surname: \"Doe\" }).limit(3).offset(2).only(\"name\", \"surname\").run(function (err, people) {\r\n    // finds people with surname='Doe', skips first 2 and limits to 3 elements,\r\n    // returning only 'name' and 'surname' properties\r\n});\r\n```\r\n\r\nYou can also chain and just get the count in the end. In this case, offset, limit and order are ignored.\r\n\r\n```js\r\nPerson.find({ surname: \"Doe\" }).count(function (err, people) {\r\n    // people = number of people with surname=\"Doe\"\r\n});\r\n```\r\n\r\nAlso available is the option to remove the selected items.\r\n\r\n```js\r\nPerson.find({ surname: \"Doe\" }).remove(function (err) {\r\n    // Does gone..\r\n});\r\n```\r\n\r\nYou can also make modifications to your instances using common Array traversal methods and save everything\r\nin the end.\r\n\r\n```js\r\nPerson.find({ surname: \"Doe\" }).each(function (person) {\r\n\tperson.surname = \"Dean\";\r\n}).save(function (err) {\r\n\t// done!\r\n});\r\n\r\nPerson.find({ surname: \"Doe\" }).each().filter(function (person) {\r\n\treturn person.age >= 18;\r\n}).sort(function (person1, person2) {\r\n\treturn person1.age < person2.age;\r\n}).get(function (people) {\r\n\t// get all people with at least 18 years, sorted by age\r\n});\r\n```\r\n\r\nOf course you could do this directly on `.find()`, but for some more complicated tasks this can be very usefull.\r\n\r\n`Model.find()` does not return an Array so you can't just chain directly. To start chaining you have to call\r\n`.each()` (with an optional callback if you want to traverse the list). You can then use the common functions\r\n`.filter()`, `.sort()` and `.forEach()` more than once.\r\n\r\nIn the end (or during the process..) you can call:\r\n- `.count()` if you just want to know how many items there are;\r\n- `.get()` to retrieve the list;\r\n- `.save()` to save all item changes.\r\n\r\n#### Conditions\r\n\r\nConditions are defined as an object where every key is a property (table column). All keys are supposed\r\nto be concatenated by the logical `AND`. Values are considered to match exactly, unless you're passing\r\nan `Array`. In this case it is considered a list to compare the property with.\r\n\r\n```js\r\n{ col1: 123, col2: \"foo\" } // `col1` = 123 AND `col2` = 'foo'\r\n{ col1: [ 1, 3, 5 ] } // `col1` IN (1, 3, 5)\r\n```\r\n\r\nIf you need other comparisons, you have to use a special object created by some helper functions. Here are\r\na few examples to describe it:\r\n\r\n```js\r\n{ col1: orm.eq(123) } // `col1` = 123 (default)\r\n{ col1: } // `col1` <> 123\r\n{ col1: } // `col1` > 123\r\n{ col1: orm.gte(123) } // `col1` >= 123\r\n{ col1: } // `col1` < 123\r\n{ col1: orm.lte(123) } // `col1` <= 123\r\n{ col1: orm.between(123, 456) } // `col1` BETWEEN 123 AND 456\r\n{ col1: + \"%\") } // `col1` like '12%'\r\n```\r\n\r\n### Caching & Integrity\r\n\r\nModel instances are cached. If multiple different queries will result in the same result, you will\r\nget the same object. If you have other systems that can change your database (or you're developing and need\r\nto make some manual changes) you should remove this feature by disabling cache. This can be done when you're\r\ndefining the Model.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n\tname    : String\r\n}, {\r\n\tcache   : false\r\n});\r\n```\r\n\r\nand also globally:\r\n\r\n```js\r\norm.connect('...', function(err, db) {\r\n  db.settings.set('instance.cache', false);\r\n});\r\n```\r\n\r\nThe cache can be configured to expire after a period of time by passing in a number instead of a\r\nboolean. The number will be considered the cache timeout in seconds (you can use floating point).\r\n\r\n**Note**: One exception about Caching is that it won't be used if an instance is not saved. For example, if\r\nyou fetch a Person and then change it, while it doesn't get saved it won't be passed from Cache.\r\n\r\n## Creating Items\r\n\r\n### Model.create(items, cb)\r\n\r\nTo insert new elements to the database use `Model.create`.\r\n\r\n```js\r\nPerson.create([\r\n\t{\r\n\t\tname: \"John\",\r\n\t\tsurname: \"Doe\",\r\n\t\tage: 25,\r\n\t\tmale: true\r\n\t},\r\n\t{\r\n\t\tname: \"Liza\",\r\n\t\tsurname: \"Kollan\",\r\n\t\tage: 19,\r\n\t\tmale: false\r\n\t}\r\n], function (err, items) {\r\n\t// err - description of the error or null\r\n\t// items - array of inserted items\r\n});\r\n```\r\n\r\n## Updating Items\r\n\r\nEvery item returned has the properties that were defined to the Model and also a couple of methods you can\r\nuse to change each item.\r\n\r\n```js\r\nPerson.get(1, function (err, John) {\r\n\ = \"Joe\";\r\n\tJohn.surname = \"Doe\";\r\n\ (err) {\r\n\t\tconsole.log(\"saved!\");\r\n\t});\r\n});\r\n```\r\n\r\nUpdating and then saving an instance can be done in a single call:\r\n\r\n```js\r\nPerson.get(1, function (err, John) {\r\n\{ name: \"Joe\", surname: \"Doe\" }, function (err) {\r\n\t\tconsole.log(\"saved!\");\r\n\t});\r\n});\r\n```\r\n\r\nIf you want to remove an instance, just do:\r\n\r\n```js\r\n// you could do this without even fetching it, look at Chaining section above\r\nPerson.get(1, function (err, John) {\r\n\tJohn.remove(function (err) {\r\n\t\tconsole.log(\"removed!\");\r\n\t});\r\n});\r\n```\r\n\r\n## Validations\r\n\r\nYou can define validations for every property of a Model. You can have one or more validations for each property.\r\nYou can also use the predefined validations or create your own.\r\n\r\n```js\r\nvar Person = db.define(\"person\", {\r\n\tname : String,\r\n\tage  : Number\r\n}, {\r\n\tvalidations : {\r\n\t\tname : orm.validators.rangeLength(1, undefined, \"missing\"), // \"missing\" is a name given to this validation, instead of default\r\n\t\tage  : [ orm.validators.rangeNumber(0, 10), orm.validators.insideList([ 1, 3, 5, 7, 9 ]) ]\r\n\t}\r\n});\r\n```\r\n\r\nThe code above defines that the `name` length must be between 1 and undefined (undefined means any) and `age`\r\nmust be a number between 0 and 10 (inclusive) but also one of the listed values. The example might not make sense\r\nbut you get the point.\r\n\r\nWhen saving an item, if it fails to validate any of the defined validations you'll get an `error` object with the property\r\nname and validation error description. This description should help you identify what happened.\r\n\r\n```js\r\nvar John = new Person({\r\n\tname : \"\",\r\n\tage : 20\r\n});\r\ (err) {\r\n\t// err.field = \"name\" , err.value = \"\" , err.msg = \"missing\"\r\n});\r\n```\r\n\r\nThe validation stops after the first validation error. If you want it to validate every property and return all validation\r\nerrors, you can change this behavior on global or local settings:\r\n\r\n```js\r\nvar orm = require(\"orm\");\r\n\r\norm.settings.set(\"instance.returnAllErrors\", true); // global or..\r\n\r\norm.connect(\"....\", function (err, db) {\r\n\tdb.settings.set(\"instance.returnAllErrors\", true); // .. local\r\n\r\n\t// ...\r\n\r\n\tvar John = new Person({\r\n\t\tname : \"\",\r\n\t\tage : 15\r\n\t});\r\n\ (err) {\r\n\t\tassert(Array.isArray(err));\r\n\t\t// err[0].field = \"name\" , err[0].value = \"\" , err[0].msg = \"missing\"\r\n\t\t// err[1].field = \"age\"  , err[1].value = 15 , err[1].msg = \"out-of-range-number\"\r\n\t\t// err[2].field = \"age\"  , err[2].value = 15 , err[2].msg = \"outside-list\"\r\n\t});\r\n});\r\n```\r\n\r\n### Predefined Validations\r\n\r\nPredefined validations accept an optional last parameter `msg` that is the `Error.msg` if it's triggered.\r\n\r\n#### `required(msg)`\r\n\r\nEnsures property is not `null` or `undefined`. It does not trigger any error if property is `0` or empty string.\r\n\r\n#### `rangeNumber(min, max, msg)`\r\n\r\nEnsures a property is a number between `min` and `max`. Any of the parameters can be passed as `undefined`\r\nto exclude a minimum or maximum value.\r\n\r\n#### `rangeLength(min, max, msg)`\r\n\r\nSame as previous validator but for property length (strings).\r\n\r\n#### `insideList(list, msg)`\r\n\r\nEnsures a property value is inside a list of values.\r\n\r\n#### `outsideList(list, msg)`\r\n\r\nEnsures a property value is not inside a list of values.\r\n\r\n#### `equalToProperty(property, msg)`\r\n\r\nEnsures a property value is not the same as another property value in the instance. This validator is good for example for\r\npassword and password repetition check.\r\n\r\n#### `notEmptyString(msg)`\r\n\r\nThis is an alias for `rangeLength(1, undefined, 'empty-string')`.\r\n\r\n#### `unique(msg)`\r\n\r\nEnsures there's not another instance in your database already with that property value. This validator is good for example for\r\nunique identifiers.\r\n\r\n#### `password([ checks, ]msg)`\r\n\r\nEnsures the property value has some defined types of characters, usually wanted in a password. `checks` is optional and\r\ndefaults to `\"luns6\"` which leans `l`owercase letters, `u`ppercase letters, `n`umbers, `s`pecial characters, with a minimum\r\nlength of `6`.\r\n\r\n#### `patterns.match(pattern, modifiers, msg)`\r\n\r\nEnsures the property value passes the regular expression pattern (and regex modifiers).\r\n\r\nThe next `patterns.*` are comodity alias to this one.\r\n\r\n#### `patterns.hexString(msg)`\r\n\r\nEnsures the property value is an hexadecimal string (uppercase or lowercase).\r\n\r\n#### ``\r\n\r\nEnsures the property value is a valid e-mail (more or less).\r\n\r\n#### `patterns.ipv4(msg)`\r\n\r\nEnsures the property value is a valid IPv4 address. It does not accept masks (example: `0` as last number is not valid).\r\n\r\n## Associations\r\n\r\nAn association is a relation between one or more tables.\r\n\r\n### hasOne\r\n\r\nIs a **many to one** relationship. It's the same as **belongs to.**<br/>\r\nEg: `Animal.hasOne('owner', Person)`.<br/>\r\nAnimal can only have one owner, but Person can have many animals.<br/>\r\nAnimal will have the `owner_id` property automatically added.\r\n\r\nThe following functions will become available:\r\n```js\r\nanimal.getOwner(function..)         // Gets owner\r\nanimal.setOwner(person, function..) // Sets owner_id\r\nanimal.hasOwner(function..)         // Checks if owner exists\r\nanimal.removeOwner()                // Sets owner_id to 0\r\n```\r\n\r\n**Reverse access**\r\n\r\n```js\r\nAnimal.hasOne('owner', Person, {reverse: 'pets'})\r\n```\r\n\r\nwill add the following:\r\n\r\n```js\r\nperson.getPets(function..)\r\nperson.setPets(cat, function..)\r\n```\r\n\r\n### hasMany\r\n\r\nIs a **many to many** relationship (includes join table).<br/>\r\nEg: `Patient.hasMany('doctors', Doctor, { why: String }, { reverse: 'patients' })`.<br/>\r\nPatient can have many different doctors. Each doctor can have many different patients.\r\n\r\nThis will create a join table `patient_doctors` when you call `Patient.sync()`:\r\n\r\n column name | type\r\n :-----------|:--------\r\n patient_id  | Integer\r\n doctor_id   | Integer\r\n why         | varchar(255)\r\n\r\nThe following functions will be available:\r\n\r\n```js\r\npatient.getDoctors(function..)           // List of doctors\r\npatient.addDoctors(docs, function...)    // Adds entries to join table\r\npatient.setDoctors(docs, function...)    // Removes existing entries in join table, adds new ones\r\npatient.hasDoctors(docs, function...)    // Checks if patient is associated to specified doctors\r\npatient.removeDoctors(docs, function...) // Removes specified doctors from join table\r\n\r\ndoctor.getPatients(function..)\r\netc...\r\n```\r\n\r\nTo associate a doctor to a patient:\r\n\r\n```js\r\npatient.addDoctor(surgeon, {why: \"remove appendix\"}, function(err) { ... } )\r\n```\r\n\r\nwhich will add `{patient_id: 4, doctor_id: 6, why: \"remove appendix\"}` to the join table.\r\n\r\n### extendsTo\r\n\r\nIf you want to split maybe optional properties into different tables or collections. Every extension will be in a new table,\r\nwhere the unique identifier of each row is the main model instance id. For example:\r\n\r\n```js\r\nvar Person = db.define(\"person\", {\r\n    name : String\r\n});\r\nvar PersonAddress = Person.extendsTo(\"address\", {\r\n    street : String,\r\n    number : Number\r\n});\r\n```\r\n\r\nThis will create a table `person` with columns `id` and `name`. The extension will create a table `person_address` with\r\ncolumns `person_id`, `street` and `number`. The methods available in the `Person` model are similar to an `hasOne`\r\nassociation. In this example you would be able to call `.getAddress(cb)`, `.setAddress(Address, cb)`, ..\r\n\r\n**Note:** you don't have to save the result from `Person.extendsTo`. It returns an extended model. You can use it to query\r\ndirectly this extended table (and even find the related model) but that's up to you. If you only want to access it using the\r\noriginal model you can just discard the return.\r\n\r\n### Examples & options\r\n\r\nIf you have a relation of 1 to n, you should use `hasOne` (belongs to) association.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n    name : String\r\n});\r\nvar Animal = db.define('animal', {\r\n    name : String\r\n});\r\nAnimal.hasOne(\"owner\", Person); // creates column 'owner_id' in 'animal' table\r\n\r\n// get animal with id = 123\r\nAnimal.get(123, function (err, animal) {\r\n    // animal is the animal model instance, if found\r\n    Foo.getOwner(function (err, person) {\r\n        // if animal has really an owner, person points to it\r\n    });\r\n});\r\n```\r\n\r\nYou can mark the `owner_id` field as required in the database by specifying the `required` option:\r\n```js\r\nAnimal.hasOne(\"owner\", Person, { required: true });\r\n```\r\n\r\nIf you prefer to use another name for the field (owner_id) you can change this parameter in the settings.\r\n\r\n```js\r\ndb.settings.set(\"properties.association_key\", \"id_{name}\"); // {name} will be replaced by 'owner' in this case\r\n```\r\n\r\n**Note: This has to be done before the association is specified.**\r\n\r\nThe `hasMany` associations can have additional properties in the association table.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n    name : String\r\n});\r\nPerson.hasMany(\"friends\", {\r\n    rate : Number\r\n});\r\n\r\nPerson.get(123, function (err, John) {\r\n    John.getFriends(function (err, friends) {\r\n        // assumes rate is another column on table person_friends\r\n        // you can access it by going to friends[N].extra.rate\r\n    });\r\n});\r\n```\r\n\r\nIf you prefer you can activate `autoFetch`.\r\nThis way associations are automatically fetched when you get or find instances of a model.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n  name : String\r\n});\r\nPerson.hasMany(\"friends\", {\r\n    rate : Number\r\n}, {\r\n    autoFetch : true\r\n});\r\n\r\nPerson.get(123, function (err, John) {\r\n    // no need to do John.getFriends() , John already has John.friends Array\r\n});\r\n```\r\n\r\nYou can also define this option globally instead of a per association basis.\r\n\r\n```js\r\nvar Person = db.define('person', {\r\n    name : String\r\n}, {\r\n    autoFetch : true\r\n});\r\nPerson.hasMany(\"friends\", {\r\n    rate : Number\r\n});\r\n```\r\n\r\nAssociations can make calls to the associated Model by using the `reverse` option. For example, if you have an\r\nassociation from ModelA to ModelB, you can create an accessor in ModelB to get instances from ModelA.\r\nConfusing? Look at the next example.\r\n\r\n```js\r\nvar Pet = db.define('pet', {\r\n    name : String\r\n});\r\nvar Person = db.define('person', {\r\n    name : String\r\n});\r\nPet.hasOne(\"owner\", Person, {\r\n    reverse : \"pets\"\r\n});\r\n\r\nPerson(4).getPets(function (err, pets) {\r\n    // although the association was made on Pet,\r\n    // Person will have an accessor (getPets)\r\n    //\r\n    // In this example, ORM will fetch all pets\r\n    // whose owner_id = 4\r\n});\r\n```\r\n\r\nThis makes even more sense when having `hasMany` associations since you can manage the *many to many*\r\nassociations from both sides.\r\n\r\n```js\r\nvar Pet = db.define('pet', {\r\n    name : String\r\n});\r\nvar Person = db.define('person', {\r\n    name : String\r\n});\r\nPerson.hasMany(\"pets\", Pet, {\r\n    bought  : Date\r\n}, {\r\n    reverse : \"owners\"\r\n});\r\n\r\nPerson(1).getPets(...);\r\nPet(2).getOwners(...);\r\n```","google":"UA-36807397-1","note":"Don't delete this file! It's used internally to help with page regeneration."}