promised-models

0.0.21 • Public • Published

Promised Models

Key features

  • promise based
  • typed attributes
  • nested models and collections
  • async calculations and validation

Install

$npm install --save promised-models

Usage

var Model = require('promises-models'),
    FashionModel = new Model.inherit({
        attributes: {
            name: Model.attributeTypes.String
        }
    }),
    model = new FashionModel({
        name: 'Kate'
    });
 
model.get('name'); // 'Kate'

Api reference (in progress)

Model sync methods

inherit Model.inherit(properties, [classPorperties])

Creates you own model class by extending Model. You can define attributes, instance/class method and properties. Inheritance is built over inherit.

var CountedModels = Model.inherit({
    __constructor: function () {
        this.__base.apply(this, arguments); //super
        this.attributes.index.set(this.__self._count); //static properties
        this.__self._count ++;
    },
    getIndex: function () {
        return this.get('index');
    }
}, {
    _count: 0,
    getCount: function () {
        return this._count;
    }
});

attributeTypes Model.attributeTypes

Namespace for predefined types of attributes. Supported types:

  • String
  • Number
  • Boolean
  • List — for storing arrays
  • Model — for nested models
  • ModelsList — for nested collections
  • Object — serializable objects

You can extend default attribute types or create your own

var DateAttribute = Model.attributeTypes.Number.inherit({
    //..
}),
FashionModel = Model.inherit({
    attributes: {
        name: Model.attributeTypes.String,
        birthDate: DateAttribute
    }
});

Note: models.attributes will be replaced in constructor with attribute instances.

var model = new FashionModel();
model.attributes.birthDate instanceof DateAttribute; //true

set model.set(attributeName, value)

Set current value of attribute.

var model = new FashionModel();
model.set('name', 'Kate');
model.attributes.name.set('Kate');
model.set({
    name: 'Kate',
    birthDate: new Date(1974, 1, 16)
});

Note: setting null is equivalent to call .unset()

get model.get(attributeName)

Get current value of attribute.

var model = new FashionModel({
    name: 'Kate',
    birthDate: new Date(1974, 1, 16)
})
model.get('name'); //Kate
model.attributes.name.get(); //Kate
model.get('some'); //throws error as unknown attribute

toJSON model.toJSON()

Return shallow copy of model data.

Note: You can create internal attributes, which wouldn't be included to returned object.

var FashionModel = new Model.inherit({
    attributes: {
        name: Model.attributeTypes.String.inherit({
            internal: true;
        }),
        sename: Model.attributeTypes.String.inherit({
            internal: true;
        }),
        fullName: Model.attributeTypes.String
    }
}),
model = new FashionModel({
    name: 'Kate',
    sename: 'Moss',
    fullName: 'Kate Moss'
});
model.toJSON(); // {fullName: 'Kate Moss'}
model.get('name'); // Kate

Note: Returned object supposed to be serializable via JSON.parse(). Due to this reason NaN and Infinity are serialized in this way:

NaN -> null
Infinity -> 'Infinity'

isChanged model.isChanged([branch])

Has model changed since init or last commit/save/fetch.

var FashionModel = Model.inherit({
        attributes: {
            name: Model.attributeTypes.String,
            weight: Model.attributeTypes.Number.inherit({
                default: 50
            })
        }
    }),
    model = new FashionModel({
        name: 'Kate',
        weight: 55
    });
model.isChanged(); //false
model.set('weight', 56);
model.isChanged(); //true

commit model.commit([branch])

Cache current model state

var model = new FashionModel();
model.set({
    name: 'Kate',
    weight: 55
});
model.isChanged();//true
model.commit();
model.isChanged();//false

revert model.revert([branch])

Revert model state to last cashed one

var model = new FashionModel({
    name: 'Kate',
    weight: 55
});
model.set('weight', 56);
model.revert();
model.get('weight'); //55
model.isChanged(); //false

Note: You can create your own cache by passing branch param.

var RENDERED = 'RENDERED';
model.on('change', function () {
    if (model.isChanged(RENDERED)) {
        View.render();
        model.commit(RENDERED);
    }
});

on model.on([attributes], events, cb, [ctx])

Add event handler for one or multiple model events.

List of events:

  • change – some of attributes have been changed
  • change:attributeNameattributeName have been changed
  • destruct – model was destructed
  • calculate – async calculations started
model.on('change', this.changeHandler, this)
     .on('change:weight change:name', this.changeHandler, this);

un model.un([attributes], events, cb, [ctx])

Unsubscribe event handler from events.

//subscribe
model.on('weight name', 'change', this.changeHandler, this);
 
//unsubscribe
model.un('change:weight change:name', this.changeHandler, this);

destruct model.destruct()

Remove all events handlers from model and removes model from collections

isSet model.isSet(attributeName)

Returns true if attribute was set via constructor or set

var model = new FashionModel();
model.isSet('name'); //false
model.set('name', 'Kate');
model.isSet('name'); //true

unset model.unset(attributeName)

Set attribute to default value and model.isSet() === 'false'

var model = new FashionModel();
model.set('name', 'Kate');
model.unset('name');
model.isSet('name'); //false
model.get('name'); //empty string (default value)

Model async methods

validate model.validate()

Validate model attributes.

var FashionModel = Model.inherit({
        attributes: {
            name: Model.attributeTypes.String.inherit({
                validate: function () {
                    return $.get('/validateName', {
                        name: this.get()
                    }).then(function () {
                        return true; //valid
                    }, function () {
                        return false; //invalid
                    });
                }
            })
        }
    }),
    model = new FashionModel();
 
model.validate().fail(function (err) {
    if (err instanceof Model.ValidationError) {
        console.log('Invalid attributes:' + err.attributes.join());
    } else {
        return err;
    }
}).done();

ready model.ready()

Fulfils when all calculations over model finished.

var FashionModel = Model.inherit({
        attributes: {
            name: Model.attributeTypes.String,
            ratingIndex: Model.attributeTypes.Number.inherit({
                calculate: function () {
                    return $.get('/rating', {
                        annualFee: this.model.get('annualFee')
                    });
                }
            }),
            annualFee: Model.attributeTypes.Number
        }
    }),
    model = new FashionModel();
 
model.set('annualFee', 1000000);
model.ready().then(function () {
    model.get('ratingIndex');
}).done();
 

fetch model.fetch()

Fetch data associated with model from storage.

var FashionModel = Model.inherit({
        attributes: {
            name: Model.attributeTypes.String
        },
        storage: Model.Storage.inherit({
            find: function (model) {
                return $.get('/models', {
                    id: model.id
                });
            }
        })
    }),
    model = new FashionModel(id);
 
model.fetch().then(function () {
    model.get('name');
}).done();

save model.save()

var FashionModel = Model.inherit({
        attributes: {
            name: Model.attributeTypes.String,
            weight: Model.attributeTypes.Number
        },
        storage: Model.Storage.inherit({
            insert: function (model) {
                return $.post('/models', model.toJSON()).then(function (result) {
                    return result.id;
                });
            },
            update: function (model) {
                return $.put('/models', model.toJSON());
            }
        })
    }),
    model = new FashionModel();
 
model.set({
    name: 'Kate',
    weight: 55
});
model.save().then(function () { //create
    model.id; //storage id
    model.set('weight', 56);
    return model.save(); //update
}).done()

remove model.remove()

Removes model from storage.

Model additional methods and properties

  • model.isNew()
  • model.isReady()
  • model.trigger(event)
  • model.calculate()
  • model.CHANGE_BRANCH
  • model.CALCULATIONS_BRANCH

These methods provided for advanced model extending. Consult source for details.

Model static methods and properties

Storage Model.Storage

Abstract class for model storage

var FashionModel = Model.inherit({
    attributes: {
        //..
    },
    storage: Model.Storage.inherit({
        //..
    })
});

Class storage Model.storage

Storage class

var SuperModel = FashionModel.inherit({
    storage: FashionModel.storage.inherit({ //extend storage from FashionModel
        //..
    })
});

Attribute Model.Attribute

Base class for model attribute

var CustomAttribute = Model.attribute.inherit({
    //..
})

Class attributes Model.attributes

Model class attributes

var SuperModel = FashionModel.inherit({
    attributes: {
        name: FashionModel.attributes.name,
        weight: FashionModel.attributes.weight.inherit({
            default: 50
        })
    }
});

Model.on([attributes], events, cb, [ctx])

Bind event on all models of class

FashionModel.on('change', this.changeHandler, this);

Model.un([attributes], events, cb, [ctx])

Unbind event on all models of class

List

Array like object returned for fields types List and ModelsList

var Podium = Model.inherit({
    attributes: {
        models: Model.attributeTypes.ModelsList(FashionModel)
    }
}),

podium = new Podium(data),
list = podium.get('models'), //instanceof List
model = list.get(0); //instanceof Model

Mutating methods

List inerits Array mutating methods: pop, push, reverse, shift, sort, splice, unshift

podium.get('models').push(new FashionModel());

list.get(index)

Get list item by index

podium.get('models').get(0);// instanceof Model

list.length()

Returns length of list

list.toArray()

Returns shallow copy of Array, wich stores List items

podium.get('models').forEach(function (model) {
    model; // instanceof Model
});

ValidationError Model.ValidationError

Error class for validation fail report

run tests

$ npm test

Package Sidebar

Install

npm i promised-models

Weekly Downloads

3

Version

0.0.21

License

none

Last publish

Collaborators

  • delfrrr
  • garmash