backbone-db
Advanced tools
Comparing version 0.4.18 to 0.4.19
126
lib/db.js
@@ -15,3 +15,3 @@ var Backbone = require('backbone'); | ||
storage = { | ||
getItem: function (key, cb) { | ||
getItem: function(key, cb) { | ||
debug('getItem: ' + key); | ||
@@ -21,3 +21,3 @@ cb(null, database[key]); | ||
}, | ||
setItem: function (key, value, cb) { | ||
setItem: function(key, value, cb) { | ||
debug('setItem: ' + key + ' = ' + value); | ||
@@ -27,3 +27,3 @@ database[key] = value; | ||
}, | ||
removeItem: function (key, cb) { | ||
removeItem: function(key, cb) { | ||
debug('removeItem: ' + key); | ||
@@ -40,3 +40,18 @@ delete database[key]; | ||
function sort(property) { | ||
debug('sorting by %s',property||''); | ||
// sort by multiple properties | ||
function multisort(properties) { | ||
return function multiCompare(a, b) { | ||
var i = 0; | ||
var result = 0; | ||
var numberOfProperties = properties.length; | ||
while(result === 0 && i < numberOfProperties) { | ||
result = sort(properties[i])(a, b); | ||
i++; | ||
} | ||
return result; | ||
}; | ||
} | ||
if (_.isArray(property)) return multisort(property); | ||
debug('sorting by %s', property || ''); | ||
var sortOrder = 1; | ||
@@ -47,6 +62,7 @@ if (property[0] === '-') { | ||
} | ||
return function (a, b) { | ||
function compare(a, b) { | ||
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0; | ||
return result * sortOrder; | ||
}; | ||
} | ||
return compare; | ||
} | ||
@@ -60,3 +76,3 @@ | ||
filterOptions.where = _.mapValues(filterOptions.where, function(val) { | ||
if(typeof val === 'object' && val.toString && val.toString().length === 24) { | ||
if (typeof val === 'object' && val.toString && val.toString().length === 24) { | ||
return val.toString(); | ||
@@ -70,7 +86,7 @@ } else { | ||
jq.on('data', function (model) { | ||
jq.on('data', function(model) { | ||
filteredModels.push(model); | ||
}); | ||
jq.on('end', function () { | ||
jq.on('end', function() { | ||
callback(null, filteredModels); | ||
@@ -88,3 +104,3 @@ }); | ||
var limit = options.limit ? options.limit : models.length; | ||
filterModels(models, options, function (err, models) { | ||
filterModels(models, options, function(err, models) { | ||
if (options.sort) models.sort(sort(options.sort)); | ||
@@ -124,3 +140,3 @@ if (options.after_id) { | ||
this.storage = getStorage(this.name); | ||
this.store().getItem(this.name, function (err, records) { | ||
this.store().getItem(this.name, function(err, records) { | ||
self.records = (records && records.split(',')) || []; | ||
@@ -132,4 +148,4 @@ }); | ||
_.extend(Backbone.Db.prototype, Backbone.Events, { | ||
save: function (cb) { | ||
this.store().setItem(this.name, JSON.stringify(this.records), function () { | ||
save: function(cb) { | ||
this.store().setItem(this.name, JSON.stringify(this.records), function() { | ||
cb(null); | ||
@@ -139,3 +155,3 @@ }); | ||
create: function (model, options, cb) { | ||
create: function(model, options, cb) { | ||
debug('CREATE: ' + JSON.stringify(model)); | ||
@@ -145,5 +161,5 @@ var self = this; | ||
function store(model) { | ||
self.store().setItem(getKey(model), JSON.stringify(model), function (err, res) { | ||
self.store().setItem(getKey(model), JSON.stringify(model), function(err, res) { | ||
self.records.push(getKey(model)); | ||
self.save(function (err) { | ||
self.save(function(err) { | ||
return cb(err, model.toJSON(options), res); | ||
@@ -155,3 +171,3 @@ }); | ||
if (model.isNew()) { | ||
this.createId(model, options, function (err, id) { | ||
this.createId(model, options, function(err, id) { | ||
store(model); | ||
@@ -164,5 +180,5 @@ }); | ||
find: function (model, options, cb) { | ||
find: function(model, options, cb) { | ||
debug('FIND: ' + JSON.stringify(model)); | ||
this.store().getItem(getKey(model), function (err, data) { | ||
this.store().getItem(getKey(model), function(err, data) { | ||
data = data && JSON.parse(data); | ||
@@ -174,3 +190,3 @@ var error = err || data ? null : new Error('not found'); | ||
findAll: function (model, options, cb) { | ||
findAll: function(model, options, cb) { | ||
debug('FINDALL: ' + JSON.stringify(options)); | ||
@@ -187,3 +203,3 @@ var self = this; | ||
var allIndexed = _.each(objectKeys, function(attr) { | ||
if(indexedKeys.indexOf(attr) > -1) { | ||
if (indexedKeys.indexOf(attr) > -1) { | ||
searchAttrs[attr] = model.get(attr); | ||
@@ -200,6 +216,6 @@ } | ||
if (this.records.length > 0) { | ||
done = _.after(this.records.length, function () { | ||
done = _.after(this.records.length, function() { | ||
queryModels(models, options, function(err, results) { | ||
if(!model.model) { | ||
if(!results || results.length === 0) { | ||
if (!model.model) { | ||
if (!results || results.length === 0) { | ||
err = err || new Error('not found'); | ||
@@ -216,4 +232,4 @@ } | ||
this.records.forEach(function (id) { | ||
self.store().getItem(id, function (err, data) { | ||
this.records.forEach(function(id) { | ||
self.store().getItem(id, function(err, data) { | ||
data = data && JSON.parse(data); | ||
@@ -226,3 +242,3 @@ models.push(data); | ||
destroy: function (model, options, cb) { | ||
destroy: function(model, options, cb) { | ||
debug('DESTROY: ' + JSON.stringify(model)); | ||
@@ -233,11 +249,11 @@ var self = this; | ||
} | ||
this.store().removeItem(getKey(model), function () { | ||
this.store().removeItem(getKey(model), function() { | ||
var found = false; | ||
self.records = _.reject(self.records, function (id) { | ||
self.records = _.reject(self.records, function(id) { | ||
var itemFound = id === getKey(model); | ||
if(!found) found = itemFound; | ||
if (!found) found = itemFound; | ||
return itemFound; | ||
}); | ||
if(!found) return cb(new Error('not found')); | ||
self.save(function (err) { | ||
if (!found) return cb(new Error('not found')); | ||
self.save(function(err) { | ||
cb(err, model); | ||
@@ -248,3 +264,3 @@ }); | ||
update: function (model, options, cb) { | ||
update: function(model, options, cb) { | ||
var self = this; | ||
@@ -264,3 +280,3 @@ debug('UPDATE: ' + JSON.stringify(model)); | ||
// Support for non plain object JSON types. | ||
if(_.isPlainObject(data) && _.isPlainObject(modelData)) { | ||
if (_.isPlainObject(data) && _.isPlainObject(modelData)) { | ||
_.merge(data, modelData); | ||
@@ -270,3 +286,3 @@ } else { | ||
} | ||
self.store().setItem(id, JSON.stringify(data), function (err, res) { | ||
self.store().setItem(id, JSON.stringify(data), function(err, res) { | ||
// if models created with id. | ||
@@ -281,3 +297,3 @@ if (self.records.indexOf(getKey(model)) === -1) { | ||
_createDefaultId: (function(id) { | ||
_createDefaultId: (function(id) { | ||
return function(callback) { | ||
@@ -289,6 +305,6 @@ debug('_createDefaultId'); | ||
createId: function (model, options, callback) { | ||
createId: function(model, options, callback) { | ||
debug('createId'); | ||
var createIdFn = model.createId ? _.bind(model.createId, model) : this._createDefaultId; | ||
createIdFn(function (err, id) { | ||
createIdFn(function(err, id) { | ||
model.set(model.idAttribute, id); | ||
@@ -299,3 +315,3 @@ callback(err); | ||
inc: function (model, options, cb) { | ||
inc: function(model, options, cb) { | ||
debug('INC:', options.inc); | ||
@@ -306,3 +322,3 @@ var self = this; | ||
var key = getKey(model); | ||
this.store().getItem(key, function (err, data) { | ||
this.store().getItem(key, function(err, data) { | ||
if (err || !data) { | ||
@@ -318,3 +334,3 @@ if (options.ignoreFailures) { | ||
data[attribute] = value; | ||
self.store().setItem(key, JSON.stringify(data), function (err, res) { | ||
self.store().setItem(key, JSON.stringify(data), function(err, res) { | ||
cb(err, data, res); | ||
@@ -326,7 +342,7 @@ }); | ||
// expose "raw" storage backend. | ||
store: function () { | ||
store: function() { | ||
return this.storage; | ||
}, | ||
sync: function (method, model, options) { | ||
sync: function(method, model, options) { | ||
options = options || {}; | ||
@@ -355,14 +371,14 @@ var self = this; | ||
switch (method) { | ||
case 'create': | ||
return db.create(model, options, callback); | ||
case 'update': | ||
return db.update(model, options, callback); | ||
case 'delete': | ||
return db.destroy(model, options, callback); | ||
case 'read': | ||
if (typeof model.get(model.idAttribute) !== 'undefined') { | ||
return db.find(model, options, callback); | ||
} else { | ||
return db.findAll(model, options, callback); | ||
} | ||
case 'create': | ||
return db.create(model, options, callback); | ||
case 'update': | ||
return db.update(model, options, callback); | ||
case 'delete': | ||
return db.destroy(model, options, callback); | ||
case 'read': | ||
if (typeof model.get(model.idAttribute) !== 'undefined') { | ||
return db.find(model, options, callback); | ||
} else { | ||
return db.findAll(model, options, callback); | ||
} | ||
} | ||
@@ -369,0 +385,0 @@ } |
{ | ||
"name": "backbone-db", | ||
"version": "0.4.18", | ||
"version": "0.4.19", | ||
"description": "Key-Value database storage interface, localStorage and in-process implementations", | ||
@@ -31,3 +31,3 @@ "main": "index.js", | ||
"mocha": "~1.18", | ||
"jshint": "~2.4.3", | ||
"jshint": "~2.4", | ||
"chai": "~1.9", | ||
@@ -34,0 +34,0 @@ "istanbul": "~0.2.4", |
var assert = require('assert'); | ||
module.exports = function (cb) { | ||
module.exports = function(cb) { | ||
var m1, m2, m3; | ||
after(function () { | ||
after(function() { | ||
if (cb) cb(); | ||
}); | ||
it('should .find from store', function (t) { | ||
it('should .find from store', function(t) { | ||
var m = new this.Collection(); | ||
m.fetch({ | ||
success: function () { | ||
success: function() { | ||
assert(m.length === 0, 'Collection should be empty'); | ||
t(); | ||
}, | ||
error: function (collection, err) { | ||
error: function(collection, err) { | ||
t(); | ||
@@ -22,3 +22,3 @@ } | ||
it('should .create from store', function (t) { | ||
it('should .create from store', function(t) { | ||
var m = new this.Collection(); | ||
@@ -29,11 +29,11 @@ assert(m.length === 0); | ||
}, { | ||
success: function (model) { | ||
success: function(model) { | ||
assert(model.get('test') === 1); | ||
m1 = model; | ||
m.fetch({ | ||
success: function () { | ||
success: function() { | ||
assert(m.length === 1, 'Collection shuld have 1 model'); | ||
t(); | ||
}, | ||
error: function (err) { | ||
error: function(err) { | ||
assert(err); | ||
@@ -44,3 +44,3 @@ } | ||
}, | ||
error: function (err) { | ||
error: function(err) { | ||
assert(err); | ||
@@ -53,3 +53,3 @@ } | ||
it('should .create 2 models', function (t) { | ||
it('should .create 2 models', function(t) { | ||
var m = new this.Collection(); | ||
@@ -61,3 +61,3 @@ assert(m.length === 0); | ||
}, { | ||
success: function (model) { | ||
success: function(model) { | ||
m2 = model; | ||
@@ -67,10 +67,10 @@ m.create({ | ||
}, { | ||
success: function (model) { | ||
success: function(model) { | ||
m3 = model; | ||
m.fetch({ | ||
success: function () { | ||
success: function() { | ||
assert(m.length === 3, 'Collection shuld have 3 model'); | ||
t(); | ||
}, | ||
error: function (model, err) { | ||
error: function(model, err) { | ||
t(err); | ||
@@ -80,3 +80,3 @@ } | ||
}, | ||
error: function (model, err) { | ||
error: function(model, err) { | ||
t(err); | ||
@@ -86,3 +86,3 @@ } | ||
}, | ||
error: function (model, err) { | ||
error: function(model, err) { | ||
t(err); | ||
@@ -93,11 +93,11 @@ } | ||
it('should fetch collection with limit', function (t) { | ||
it('should fetch collection with limit', function(t) { | ||
var collection = new this.Collection(); | ||
collection.fetch({ | ||
limit: 2, | ||
success: function () { | ||
success: function() { | ||
assert.equal(collection.length, 2); | ||
t(); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -108,3 +108,3 @@ } | ||
it('should fetch collection with offset', function (t) { | ||
it('should fetch collection with offset', function(t) { | ||
var collection = new this.Collection(); | ||
@@ -114,9 +114,9 @@ collection.fetch({ | ||
offset: 2, | ||
success: function () { | ||
success: function() { | ||
var at0 = collection.at(0); | ||
assert.equal(collection.length, 1); | ||
assert.ok(''+at0.get(at0.idAttribute) === ''+m3.get(m3.idAttribute)); | ||
assert.ok('' + at0.get(at0.idAttribute) === '' + m3.get(m3.idAttribute)); | ||
t(); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -127,3 +127,3 @@ } | ||
it('should fetch collection with after_id', function (t) { | ||
it('should fetch collection with after_id', function(t) { | ||
var collection = new this.Collection(); | ||
@@ -133,8 +133,8 @@ collection.fetch({ | ||
after_id: m2.get(m2.idAttribute), | ||
success: function () { | ||
assert.equal(''+collection.at(0).get(collection.at(0).idAttribute), ''+m3.get(m3.idAttribute)); | ||
success: function() { | ||
assert.equal('' + collection.at(0).get(collection.at(0).idAttribute), '' + m3.get(m3.idAttribute)); | ||
assert.equal(collection.length, 1); | ||
t(); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -145,3 +145,3 @@ } | ||
it('should fetch collection with before_id', function (t) { | ||
it('should fetch collection with before_id', function(t) { | ||
var collection = new this.Collection(); | ||
@@ -151,10 +151,10 @@ collection.fetch({ | ||
before_id: m3.get(m3.idAttribute), | ||
success: function () { | ||
success: function() { | ||
var at0 = collection.at(0); | ||
var at1 = collection.at(1); | ||
assert.equal(''+at0.get(at0.idAttribute), ''+m1.get(m1.idAttribute)); | ||
assert.equal(''+at1.get(at0.idAttribute), ''+m2.get(m1.idAttribute)); | ||
assert.equal('' + at0.get(at0.idAttribute), '' + m1.get(m1.idAttribute)); | ||
assert.equal('' + at1.get(at0.idAttribute), '' + m2.get(m1.idAttribute)); | ||
t(); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -165,11 +165,11 @@ } | ||
it('should fetch collection sorted by given field', function (t) { | ||
it('should fetch collection sorted by given field', function(t) { | ||
var collection = new this.Collection(); | ||
collection.fetch({ | ||
sort: '-test', | ||
success: function () { | ||
success: function() { | ||
assert.equal(collection.at(0).get('test'), 2); | ||
t(); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -180,9 +180,24 @@ } | ||
it('should fetch collection filtered with given attributes', function (t) { | ||
it('should fetch collection sorted by multiple fields', function(t) { | ||
var collection = new this.Collection(); | ||
collection.fetch({ | ||
sort: ['test', 'id'], | ||
success: function() { | ||
assert.equal(collection.at(1).id, 4); | ||
t(); | ||
}, | ||
error: function(coll, err) { | ||
t(err); | ||
} | ||
}); | ||
}); | ||
it('should fetch collection filtered with given attributes', function(t) { | ||
var collection = new this.Collection(); | ||
collection.fetch({ | ||
where: { | ||
test: 2 | ||
}, | ||
success: function () { | ||
success: function() { | ||
assert.equal(collection.length, 1); | ||
@@ -192,3 +207,3 @@ assert.equal(collection.at(0).get('test'), 2); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -199,3 +214,3 @@ } | ||
it('should fetch collection filtered with array value', function (t) { | ||
it('should fetch collection filtered with array value', function(t) { | ||
var collection = new this.Collection(); | ||
@@ -208,3 +223,3 @@ collection.fetch({ | ||
}, | ||
success: function () { | ||
success: function() { | ||
assert.equal(collection.length, 1); | ||
@@ -214,3 +229,3 @@ assert.equal(collection.at(0).get('test'), 1); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -221,3 +236,3 @@ } | ||
it('should fetch collection filtered with multiple array values', function (t) { | ||
it('should fetch collection filtered with multiple array values', function(t) { | ||
var collection = new this.Collection(); | ||
@@ -230,3 +245,3 @@ collection.fetch({ | ||
}, | ||
success: function () { | ||
success: function() { | ||
assert.equal(collection.length, 1); | ||
@@ -236,3 +251,3 @@ assert.equal(collection.at(0).get('test'), 1); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -243,3 +258,3 @@ } | ||
it('should query models with $ne', function (t) { | ||
it('should query models with $ne', function(t) { | ||
var collection = new this.Collection(); | ||
@@ -252,3 +267,3 @@ collection.fetch({ | ||
}, | ||
success: function () { | ||
success: function() { | ||
assert.equal(collection.length, 1); | ||
@@ -258,3 +273,3 @@ assert.equal(collection.at(0).get('test'), 2); | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -265,17 +280,17 @@ } | ||
it('should remove a model from collection when destroyed', function (t) { | ||
it('should remove a model from collection when destroyed', function(t) { | ||
var m = new this.Collection(); | ||
m.fetch({ | ||
success: function () { | ||
success: function() { | ||
assert(m.length === 3); | ||
var model = m.at(2); | ||
model.destroy({ | ||
success: function () { | ||
success: function() { | ||
assert(m.length === 2, 'model was not removed from collection'); | ||
m.fetch({ | ||
success: function () { | ||
success: function() { | ||
assert(m.length === 2, 'model was not removed from collection when fetched'); | ||
t(); | ||
}, | ||
error: function (model, err) { | ||
error: function(model, err) { | ||
t(err); | ||
@@ -285,3 +300,3 @@ } | ||
}, | ||
error: function (model, err) { | ||
error: function(model, err) { | ||
t(err); | ||
@@ -292,3 +307,3 @@ }, | ||
}, | ||
error: function (coll, err) { | ||
error: function(coll, err) { | ||
t(err); | ||
@@ -295,0 +310,0 @@ } |
32089
878