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');
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);
this.attributes.index.set(this.__self._count);
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 arraysModel
— for nested modelsModelsList
— for nested collectionsObject
— 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;
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');
model.attributes.name.get();
model.get('some');
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();
model.get('name');
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();
model.set('weight', 56);
model.isChanged();
commit model.commit([branch])
Cache current model state
var model = new FashionModel();
model.set({
name: 'Kate',
weight: 55
});
model.isChanged();
model.commit();
model.isChanged();
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');
model.isChanged();
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 changedchange:attributeName
– attributeName
have been changeddestruct
– model was destructedcalculate
– 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.
model.on('weight name', 'change', this.changeHandler, this);
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');
model.set('name', 'Kate');
model.isSet('name');
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');
model.get('name');
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;
}, function () {
return false;
});
}
})
}
}),
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 () {
model.id;
model.set('weight', 56);
return model.save();
}).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({
})
});
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