Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions component.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "model",
"repo": "component/model",
"description": "Elegant data models",
"version": "0.0.1",
"version": "0.0.2",
"keywords": [
"collection",
"model",
Expand All @@ -12,10 +12,10 @@
],
"dependencies": {
"component/each": "*",
"component/json": "*",
"component/emitter": "*",
"component/collection": "*",
"visionmedia/superagent": "*"
"visionmedia/superagent": "*",
"ForbesLindesay/is-browser": "*"
},
"development": {
"component/reactive": "*",
Expand All @@ -25,8 +25,10 @@
"scripts": [
"lib/index.js",
"lib/static.js",
"lib/proto.js"
"lib/proto.js",
"lib/common.js",
"lib/sync.js"
],
"main": "lib/index.js",
"license": "MIT"
}
}
11 changes: 11 additions & 0 deletions lib/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if(require('is-browser')) {
exports.emitter = require('emitter');
exports.collection = require('collection');
exports.each = require('each');
} else {
exports.emitter = require('emitter-component');
exports.collection = Array;
exports.each = function(arr, fn) {
return arr.forEach(fn);
};
}
8 changes: 5 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
* Module dependencies.
*/

var proto = require('./proto')
, statics = require('./static')
, Emitter = require('emitter');
var proto = require('./proto'),
statics = require('./static'),
common = require('./common'),
Emitter = common.emitter;

/**
* Expose `createModel`.
Expand Down Expand Up @@ -48,6 +49,7 @@ function createModel(name) {
model.modelName = name;
model.base = '/' + name.toLowerCase();
model.attrs = {};
model.sync = {};
model.validators = [];
for (var key in statics) model[key] = statics[key];

Expand Down
120 changes: 84 additions & 36 deletions lib/proto.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
* Module dependencies.
*/

var Emitter = require('emitter')
, request = require('superagent')
, JSON = require('json')
, each = require('each')
, noop = function(){};
var sync = require('./sync'),
common = require('./common'),
Emitter = common.emitter,
each = common.each,
noop = function(){};

/**
* Mixin emitter.
Expand Down Expand Up @@ -124,20 +124,25 @@ exports.validate = function(){
* @api public
*/

exports.remove = function(fn){
fn = fn || noop;
exports.remove = function(){
var args = [].slice.call(arguments),
fn = args.pop() || noop,
self = this,
remove = this.model.sync.remove || sync.remove;

if (this.isNew()) return fn(new Error('not saved'));
var self = this;
var url = this.url();
this.model.emit('removing', this);
this.emit('removing');
request.del(url, function(res){
if (res.error) return fn(error(res));

this.run('removing', function() {
remove.apply(self, args.concat(res));
});

function res(err, body) {
if(err) return fn(error(err));
self.removed = true;
self.model.emit('remove', self);
self.emit('remove');
fn();
});
}
};

/**
Expand All @@ -152,22 +157,28 @@ exports.remove = function(fn){
* @api public
*/

exports.save = function(fn){
if (!this.isNew()) return this.update(fn);
var self = this;
var url = this.model.url();
fn = fn || noop;
exports.save = function(){
if (!this.isNew()) return this.update.apply(this, arguments);

var args = [].slice.call(arguments),
fn = args.pop() || noop,
self = this,
save = this.model.sync.save || sync.save;

if (!this.isValid()) return fn(new Error('validation failed'));
this.model.emit('saving', this);
this.emit('saving');
request.post(url, self, function(res){
if (res.error) return fn(error(res));
if (res.body) self.primary(res.body.id);

this.run('saving', function() {
save.apply(self, args.concat(res));
});

function res(err, body) {
if (err) return fn(error(err));
if (body) self.primary(body.id || body._id);
self.dirty = {};
self.model.emit('save', self);
self.emit('save');
fn();
});
}
};

/**
Expand All @@ -177,20 +188,27 @@ exports.save = function(fn){
* @api private
*/

exports.update = function(fn){
var self = this;
var url = this.url();
fn = fn || noop;
exports.update = function() {
var args = [].slice.call(arguments),
fn = args.pop() || noop,
self = this,
changed = this.changed(),
update = this.model.sync.update || sync.update;

if(!changed) return fn(null, this);
if (!this.isValid()) return fn(new Error('validation failed'));
this.model.emit('saving', this);
this.emit('saving');
request.put(url, self, function(res){
if (res.error) return fn(error(res));

this.run('saving', function() {
update.apply(self, args.concat(res));
});

function res(err) {
if(err) return fn(error(err));
self.dirty = {};
self.model.emit('save', self);
self.emit('save');
fn();
});
return fn();
}
};

/**
Expand Down Expand Up @@ -275,4 +293,34 @@ exports.toJSON = function(){

function error(res) {
return new Error('got ' + res.status + ' response');
}
}

/**
* Run functions beforehand
*
* @param {String} event
* @param {Function} fn
* @api private
*/

exports.run = function(event, done) {
var fns = this.model.listeners(event).concat(this.listeners(event)),
pending = 0;

function next() {
if(!--pending) return done();
}

for (var i = 0, len = fns.length; i < len; i++) {
var fn = fns[i];
if (fn.length > 1) {
pending++;
fn(this, next);
} else {
fn(this);
}
}

if(!pending) return done();
};

65 changes: 40 additions & 25 deletions lib/static.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
* Module dependencies.
*/

var request = require('superagent')
, Collection = require('collection')
, noop = function(){};
var sync = require('./sync'),
common = require('./common'),
Collection = common.collection,
noop = function(){};

/**
* Construct a url to the given `path`.
Expand Down Expand Up @@ -93,14 +94,18 @@ exports.attr = function(name, options){
* @api public
*/

exports.removeAll = function(fn){
fn = fn || noop;
var self = this;
var url = this.url('all');
request.del(url, function(res){
if (res.error) return fn(error(res));
exports.removeAll = function() {
var args = [].slice.call(arguments),
fn = args.pop() || noop,
self = this,
removeAll = this.sync.removeAll || sync.removeAll;

removeAll.apply(this, args.concat(res));

function res(err, body) {
if(err) return fn(error(err));
fn();
});
}
};

/**
Expand All @@ -110,17 +115,22 @@ exports.removeAll = function(fn){
* @api public
*/

exports.all = function(fn){
var self = this;
var url = this.url('all');
request.get(url, function(res){
if (res.error) return fn(error(res));
exports.all = function() {
var args = [].slice.call(arguments),
fn = args.pop(),
self = this,
all = this.sync.all || sync.all;

all.apply(this, args.concat(res));

function res(err, body) {
if (err) return fn(err);
var col = new Collection;
for (var i = 0, len = res.body.length; i < len; ++i) {
col.push(new self(res.body[i]));
for (var i = 0, len = body.length; i < len; ++i) {
col.push(new self(body[i]));
}
fn(null, col);
});
}
};

/**
Expand All @@ -131,14 +141,19 @@ exports.all = function(fn){
* @api public
*/

exports.get = function(id, fn){
var self = this;
var url = this.url(id);
request.get(url, function(res){
if (res.error) return fn(error(res));
var model = new self(res.body);
exports.get = function() {
var args = [].slice.call(arguments),
fn = args.pop(),
self = this,
get = this.sync.get || sync.get;

get.apply(this, args.concat(res));

function res(err, body) {
if(err) return fn(err);
var model = new self(body);
fn(null, model);
});
}
};

/**
Expand Down
Loading