## Contents - [Getting started](#getting) - [Installation](#install) - [Configuration](#config) <br/><br/> - [Models](#models) - [Defining Models](#m-definition) - [Validating Properties](#m-validate) - [Instantiating Models](#m-instance) - [Finding Models](#m-find) - [Getters/Setters](#m-getset) - [JSON](#m-json) <br/><br/> - [Relationships](#m-rel) - [One to one](#m-onetoone) - [One to many](#m-onetomany) - [Many to Many](#m-manytomany) - [Load](#m-load) <a id="getting"></a> ## Getting started <a id="install"></a> #### Installation ``` $ npm install hater ``` <a id="config"></a> #### Configuration First of all, you need to choose which SQL dialect to use and to connect to the database, this is as simple as this: ```javascript var hater = require('hater'); hater.connect('postgresql', 'tcp://user:password@host/databaseName'); ``` <a id="models"></a> ## Models <a id="m-definition"></a> #### Defining Models To define a model you only need to invoke the ```.define()``` method from ```hater``` ```javascript var myModel = hater.define('mymodel'); ``` To extend a Model's base prototype you can pass a second argument ```javascript var myModel = hater.define('mymodel', { fullName: function() { return this.get('name') + this.get('surname'); }; }); ``` To specify the Model's schema just pass a configuration object to ```.schema()``` ```javascript myModel.schema({ name : hater.Types.String(), surname: hater.Types.String({length: 32}) }); ``` Tables are created auto-magically \ò/. <a id="m-validate"></a> #### Validating Properties ```hater``` uses ```revalidator``` to validate properties, [check it out](https://github.com/flatiron/revalidator) to see how it works ```javascript var Model = hater.define('model'); Model.schema({ test: hater.Types.String({ validate: { minLength: 5 } }); }) ``` <a id="m-instance"></a> #### Instantiating Models To create a model simply use use ```new``` or call ```.create()``` ```javascript // these three methods are equivalent var instance = new myModel({ name : 'john', surname: 'doe' }); instance.save(function(e) { // do something }); myModel.create({ name : 'john', surname: 'doe' }, function(e, instance) { // do something }); var instance2 = new myModel(); instance2.set('name', 'john'); instance2.set('surname', 'doe'); instance2.save(function(e) { // do something }); ``` <a id="m-find"></a> #### Find Hater provides ```find()``` and ```findOne``` to find documents in the database. ```javascript Model.find({ where: { id: 1 }, limit: { model: [0,10] } }, function(e. models) { // models in an array }); Model.findOne({ where: { id: 1 } }, function(e, model) { // here model is an instance }); ``` The first object can have: - where (example: ```{ where: { id: 1, name: 'test' } }```) - limit (example: ```{ limit: { name: 10 } }``` or ```{ limit: { name: [10, 20] } }``` - fetch (example: ```{ fetch: ["children"] }```, check Relationships to see how to use it) Find is recursive, so you can also query for children's properties (see also Relationships below): ```javascript Model.find({ where: { children: { name: 'test' } } }, function(e, res) { // finds all models that have a children with name 'test' }); ``` <a id="m-getset"></a> #### Getters / Setters Getters and Setters are slower than regular functions in JS, therefore we decided to implement a ```get()``` and ```set()``` function ```javascript instance.get('property'); instance.set('property', 'newValue'); ``` <a id="m-json"></a> #### JSON JSON.stringify returns the instance's properties with their respective values ```javascript JSON.stringify(instance); // {"key": "value", "key2": "value2" ... } ``` <a id="m-rel"></a> ## Relationships Hater supports: - One To One - One To Many - Many To Many <a id="m-onetoone"></a> #### One to One To link one model to another: ``` instance.set('modelName', modelInstance); ``` Example of a one to one relationship: ```javascript var Model = hater.define('model'); Model.schema({ ... }); var Other = hater.define('other'); Other.schema({ ... }); hater.Relationships.oneToOne(Model, Other); var m = new Model(); m.set('other', new Other()); m.save(); Other.findOne({ where: { id: m.get('other').get('id') }, fetch: ["model"] }, function(e, res) { other.get('model') // is m }); ``` ```fetch: ["model"]``` is a special clause that tells ```hater``` to pre-load datas that are related to the one we are querying <a id="m-onetomany"></a> #### One to Many To set an instance's children ``` instance.set('pluralOfChildName', [childInstance, childInstance]); ``` Example of a one to many relationship: ```javascript // Model and Other from previous example hater.Relationships.oneToMany(Model, Other); var m = new Model(); m.set('others', [new Other(), new Other()]); m.save(function() { Model.findOne({ where: { id: m.get('id') }, fetch: ["others"] }, function(e, res) { res.get('others') // is the array we set in m }); }); ``` We can also filter the children via the where clause ```javascript Model.findOne({ where: { id: m.get('id'), others: { name: 'test' }, fetch: ["others"] }, function(e, res) { res.get('others') // every others.name will be 'lol' }); ``` <a id="m-manytomany"></a> #### Many To Many To set relationships between instances ``` instance.set('pluralOfOtherModelName', [instanceOther, instanceOther]); ``` Example of a many to many relationship: ```javascript // Model and Other from previous example hater.Relationships.manyToMany(Model, Other); var m = new Model(); m.set('others', [new Other(), new Other()]); m.save(function(e) { Other.find({ fetch: ["models"] }, function(e, res) { var o = res.shift(); o.get('models')[0] // is the m we saved }); }); ``` <a id="m-load"></a> ### Load If you want to lazy load relationships (eg in the many to many case) you can use ```.load()``` ```javascript One.findOne({ where: { id: 1 } }, function(e, instance) { instance.load(["others"], function(e) { instange.get("others") // relationship }); }); ```