backbone-db-redis
Advanced tools
Comparing version 0.0.2 to 0.0.3
169
index.js
@@ -5,6 +5,7 @@ var _ = require('underscore') | ||
, redis = require('redis') | ||
, debug = require('debug')('backbone-db-redis'); | ||
, debug = require('debug')('backbone-db-redis') | ||
, indexing = require('./lib/indexing') | ||
, query = require('./lib/query'); | ||
Backbone.RedisDb = function(name, client) { | ||
@@ -19,3 +20,3 @@ this.name = name || ""; | ||
Backbone.RedisDb.prototype.key = function(key) { | ||
if(this.name == "") { | ||
if(this.name === "") { | ||
return key; | ||
@@ -27,5 +28,4 @@ } else { | ||
Backbone.RedisDb.sync = Db.sync | ||
Backbone.RedisDb.sync = Db.sync; | ||
_.extend(Backbone.RedisDb.prototype, Db.prototype, { | ||
@@ -42,5 +42,5 @@ createClient: function() { | ||
if(options.url) { | ||
key = typeof options.url == "function" ? options.url() : options.url; | ||
key = typeof options.url === "function" ? options.url() : options.url; | ||
} else if(model.url) { | ||
key = typeof model.url == "function" ? model.url() : model.url; | ||
key = typeof model.url === "function" ? model.url() : model.url; | ||
} else if(model.id) { | ||
@@ -52,4 +52,4 @@ key = model.id; | ||
findAll: function(model, options, callback) { | ||
debug('findAll '+model.url()); | ||
options = options || {}; | ||
debug('findAll ' + model.url()); | ||
var collectionKey = this._getKey(model, options); | ||
@@ -59,14 +59,10 @@ if(model.model) { | ||
var modelKey = this._getKey(m, {}); | ||
var start = options.start || "0"; | ||
var end = options.end || "-1"; | ||
var key = this._getKey(model, {}); | ||
debug("redis sort "+collectionKey+ ' BY nosort GET '+modelKey+':*'); | ||
this.redis.sort(collectionKey, "BY", "nosort" ,"GET", modelKey+':*', function(err, res) { | ||
if(res) { | ||
res = res.map(function(data) { | ||
return data && JSON.parse(data); | ||
}); | ||
} | ||
callback(err, res); | ||
}); | ||
var dbOpts = { | ||
db: this, | ||
model: model, | ||
modelKey: modelKey, | ||
collectionKey: collectionKey, | ||
indexes: m.indexes | ||
}; | ||
query.queryModels(options, dbOpts, callback); | ||
} else { | ||
@@ -82,3 +78,3 @@ this.redis.get(collectionKey, function(err, data) { | ||
debug('find: '+key); | ||
debug('find: ' + key); | ||
this.redis.get(key, function(err, data) { | ||
@@ -92,7 +88,7 @@ data = data && JSON.parse(data); | ||
var key = this._getKey(model, options); | ||
debug('Create '+key); | ||
debug('create: ' + key); | ||
if (model.isNew()) { | ||
self.createId(model, options, function(err, id) { | ||
if(err || !id) { | ||
return callback(err); | ||
return callback(err || new Error('id is missing')); | ||
} | ||
@@ -125,8 +121,133 @@ model.set(model.idAttribute, id); | ||
self.redis.sadd(setKey, modelKey, function(err, res) { | ||
callback(err, model.toJSON()); | ||
self._updateIndexes(model, options, callback); | ||
}); | ||
} else { | ||
self._updateIndexes(model, options, callback); | ||
} | ||
}); | ||
}, | ||
destroy: function(model, options, callback) { | ||
var self = this; | ||
var key = this._getKey(model, options); | ||
debug("DESTROY: " + key); | ||
if (model.isNew()) { | ||
return false; | ||
} | ||
function delKey() { | ||
debug('removing key: ' + key); | ||
self.redis.del(key, function(err, res) { | ||
callback(err, model.toJSON()); | ||
}); | ||
} | ||
this._updateIndexes(model, _.extend({operation: 'delete'}, options), function(err) { | ||
if(model.collection) { | ||
var setKey = self._getKey(model.collection, {}); | ||
var modelKey = model.get(model.idAttribute); | ||
debug('removing model ' + modelKey + " from " + setKey); | ||
self.redis.srem(setKey, modelKey, function(err, res) { | ||
if(err) return callback(err); | ||
delKey(); | ||
}); | ||
} else { | ||
debug('model has no collection specified'); | ||
delKey(); | ||
} | ||
}); | ||
}, | ||
addToIndex: function(collection, model, options, cb) { | ||
var setKey = collection.indexKey; | ||
var key = model.id; | ||
debug('adding model ' + key + ' to ' + setKey); | ||
if(collection.indexSort) { | ||
this.redis.zadd(setKey, collection.indexSort(model), key, cb); | ||
} else { | ||
this.redis.sadd(setKey, key, function(err, res) { | ||
cb(err, res); | ||
}); | ||
} | ||
}, | ||
readFromIndex: function(collection, options, cb) { | ||
var done = function(err, keys) { | ||
var models = []; | ||
_.each(keys, function(id) { | ||
models.push({id: id}); | ||
}); | ||
collection.set(models, options); | ||
return cb(err, models); | ||
}; | ||
var setKey = collection.indexKey; | ||
var readFn = collection.indexSort | ||
? _.bind(this.redis.zrevrange, this.redis, setKey, 0, -1) | ||
: _.bind(this.redis.smembers, this.redis, setKey); | ||
debug('reading keys from: ' + setKey); | ||
readFn(done); | ||
}, | ||
removeFromIndex: function(collection, models, options, cb) { | ||
var setKey = collection.indexKey; | ||
var keys = _.pluck(models, models[0].idAttribute); | ||
var cmd = [setKey].concat(keys); | ||
debug('removing key: ' + keys +' from: ' + setKey); | ||
if(collection.indexSort) { | ||
this.redis.zrem(cmd, cb); | ||
} else { | ||
this.redis.srem(cmd, cb); | ||
} | ||
}, | ||
existsInIndex: function(collection, model, options, cb) { | ||
var setKey = collection.indexKey; | ||
var key = model.id; | ||
debug('check existance for: ' + key + ' in: ' + setKey); | ||
function done(err, rank) { | ||
cb(err, rank !== null); | ||
} | ||
if(collection.indexSort) { | ||
this.redis.zrank(setKey, key, done); | ||
} else { | ||
this.redis.sismember(setKey, key, function(err, isMember) { | ||
cb(err, isMember === 1); | ||
}); | ||
} | ||
}, | ||
indexCount: function(collection, options, cb) { | ||
var setKey = collection.indexKey; | ||
debug('get count for: ' + setKey); | ||
if(collection.indexSort) { | ||
this.redis.zcard(setKey, cb); | ||
} else { | ||
this.redis.scard(setKey, cb); | ||
} | ||
}, | ||
findKeys: function(collection, options, cb) { | ||
var prefix = options.prefix || (this.name + ':'); | ||
this.redis.keys(prefix + options.keys + '*', cb); | ||
}, | ||
_updateIndexes: function(model, options, callback) { | ||
if(!model.indexes) { | ||
debug('nothing to index'); | ||
return callback(null, model.toJSON()); | ||
} | ||
var operation = options.operation || 'add'; | ||
var indexingOpts = { | ||
db: this, | ||
indexes: model.indexes, | ||
data: model.attributes, | ||
prevData: operation === 'delete' ? model.attributes : model.previousAttributes(), | ||
operation: operation, | ||
baseKey: model.collection ? model.collection.type : model.type, | ||
id: model.id | ||
}; | ||
indexing.updateIndexes(indexingOpts, callback); | ||
} | ||
@@ -133,0 +254,0 @@ }); |
@@ -1,2 +0,2 @@ | ||
var Deferred = require('backbone-deferred'); | ||
var Deferred = require('backbone-promises'); | ||
var Backbone = require('backbone'); | ||
@@ -3,0 +3,0 @@ var debug = require('debug')('backbone-db-redis:hash'); |
@@ -1,2 +0,2 @@ | ||
var Deferred = require('backbone-deferred'); | ||
var Deferred = require('backbone-promises'); | ||
var Backbone = require('backbone'); | ||
@@ -3,0 +3,0 @@ |
@@ -1,2 +0,2 @@ | ||
var Deferred = require('backbone-deferred'); | ||
var Deferred = require('backbone-promises'); | ||
var Backbone = require('backbone'); | ||
@@ -3,0 +3,0 @@ var debug = require('debug')('backbone-db-redis:set'); |
@@ -1,2 +0,2 @@ | ||
var Deferred = require('backbone-deferred'); | ||
var Deferred = require('backbone-promises'); | ||
var Backbone = require('backbone'); | ||
@@ -3,0 +3,0 @@ |
{ | ||
"name": "backbone-db-redis", | ||
"version": "0.0.2", | ||
"version": "0.0.3", | ||
"description": "Redis driver for Backbone.Db", | ||
@@ -13,8 +13,13 @@ "main": "index.js", | ||
"dependencies": { | ||
"backbone": "~1.0.0", | ||
"backbone": "~1.1.0", | ||
"underscore": "~1.4.4", | ||
"redis": "~0.8.4", | ||
"debug": "~0.7.2", | ||
"backbone-deferred": "git+ssh://git@github.com/Applifier/backbone-deferred.git" | ||
"backbone-db": "~0.3.0", | ||
"backbone-promises": "~0.1.8", | ||
"when": "~2.7.0" | ||
}, | ||
"devDependencies": { | ||
"mocha": "~1.15.1" | ||
} | ||
} |
@@ -24,2 +24,48 @@ ## Usage | ||
}); | ||
``` | ||
``` | ||
### Indexing: | ||
Model can define Array typed property "indexes", which defines which attributes are indexed. Example: | ||
```js | ||
var MyModel = Model.extend({ | ||
indexes: [ | ||
{ | ||
property: 'value', | ||
sort: 'asc' | ||
}, | ||
{ | ||
property: 'id', | ||
sort: function() { | ||
return Date.now(); | ||
}, | ||
dependencies: [ | ||
{ | ||
// add to index if attribute "featured" is set to true | ||
attribute: 'featured', | ||
value: true | ||
} | ||
], | ||
key: 'z:mymodels:featured' | ||
} | ||
] | ||
}); | ||
``` | ||
#### property | ||
Model's attribute to be indexed | ||
### sort | ||
If defined attribute index is stored in sorted set. If defined as function, score will be calculated with given function. If not defined attribute is indexed in unordered set. | ||
### dependencies | ||
Index attribute only if defined dependencies are met. | ||
### key | ||
If defined, store index in given set key, otherwise created automatically. |
var assert = require('assert'); | ||
var _ = require('underscore'); | ||
var RedisDb = require('../'); | ||
var Backbone = require('backbone'); | ||
var Deferred = require('backbone-deferred'); | ||
var Model = Deferred.Model; | ||
var Collection = Deferred.Collection; | ||
var store = new RedisDb('test'); | ||
var setup = require('./setup'); | ||
var MyCollection = setup.MyCollection; | ||
var MyModel = setup.MyModel; | ||
var MyModel = Model.extend({ | ||
db: store, | ||
sync: RedisDb.sync, | ||
url: function() { | ||
var key = 'mymodel'; | ||
if(!this.isNew()) { | ||
key += ':' + this.get(this.idAttribute); | ||
} | ||
return key; | ||
} | ||
}); | ||
describe('RedisDB#Collection', function() { | ||
var testCol = new MyCollection(); | ||
var testModel; | ||
var MyCollection = Collection.extend({ | ||
db: store, | ||
sync: RedisDb.sync, | ||
model: MyModel, | ||
url: function() { | ||
return 'mymodels'; | ||
} | ||
}); | ||
after(function(done) { | ||
setup.clearDb(function(err) { | ||
done(err); | ||
}); | ||
}); | ||
var testCol = new MyCollection(); | ||
it('should create a model', function(done) { | ||
testCol | ||
.create({'id_check': 1}, { wait: true }) | ||
.then(function(m) { | ||
assert(m.get('id_check') === testCol.at(0).get('id_check')); | ||
testModel = m; | ||
done(); | ||
}).otherwise(done); | ||
}); | ||
describe('RedisDB', function() { | ||
describe('#Collection', function() { | ||
it('should be able to create', function(t) { | ||
testCol.create({"id_check":1},{ wait: true }).done(function(m) { | ||
assert(m.get('id_check') == testCol.at(0).get('id_check')); | ||
var m2 = new MyModel({id:1}); | ||
m2.fetch().done(function() { | ||
assert(m.get('id_check') == m2.get('id_check')); | ||
t(); | ||
}); | ||
}).fail(function(err) { | ||
throw err; | ||
}); | ||
}); | ||
it('should save & loadits member urls to its set', function(t) { | ||
var a = new MyCollection(); | ||
a.fetch().done(function(c, a) { | ||
//assert(c.at(0) != null); | ||
t(); | ||
}); | ||
}); | ||
it('should have deferred .create', function(t) { | ||
var a = new MyCollection(); | ||
a.create({data:"xyz"}).done(function(m) { | ||
assert(m.get("data") == "xyz"); | ||
t(); | ||
}); | ||
}); | ||
it('should fetch created model', function(done) { | ||
var m2 = new MyModel({id: testModel.id}); | ||
m2.fetch().then(function(m) { | ||
assert(m.get('id_check') === m2.get('id_check')); | ||
done(); | ||
}).otherwise(done); | ||
}); | ||
it('should have deferred .fetch', function(t) { | ||
var a = new MyCollection(); | ||
a.fetch().done(function() { | ||
t(); | ||
}); | ||
}); | ||
it('should fetch collection models', function(done) { | ||
var collection = new MyCollection(); | ||
collection | ||
.fetch() | ||
.then(function(c) { | ||
assert(collection.length === 1); | ||
assert(c.at(0)); | ||
done(); | ||
}).otherwise(done); | ||
}); | ||
}); | ||
it('should remove model from collection', function(done) { | ||
var testId = testModel.id; | ||
testModel | ||
.destroy() | ||
.then(function() { | ||
var a = new MyCollection(); | ||
a.fetch().then(function() { | ||
var removedModel = a.where({id: testId}); | ||
assert(removedModel.length === 0); | ||
done(); | ||
}).otherwise(done); | ||
}).otherwise(done); | ||
}); | ||
}); |
var assert = require('assert'); | ||
var _ = require('underscore'); | ||
var RedisDb = require('../'); | ||
var Backbone = require('backbone'); | ||
var Model = require('backbone-deferred').Model; | ||
var setup = require('./setup'); | ||
var MyModel = setup.MyModel; | ||
var store = new RedisDb('mymodel'); | ||
var MyModel = Model.extend({ | ||
db: store, | ||
sync: RedisDb.sync, | ||
url: function() { | ||
var key = 'mymodel'; | ||
if(!this.isNew()) { | ||
key += ':' + this.id; | ||
} | ||
return key; | ||
} | ||
}); | ||
describe('RedisDB', function() { | ||
@@ -26,6 +9,5 @@ describe('#Model', function() { | ||
var m = new MyModel({id:1, "asd":"das"}); | ||
m.db = store; | ||
m.save().done(function() { | ||
m.save().then(function() { | ||
var m2 = new MyModel({id:1}); | ||
m2.fetch().done(function() { | ||
m2.fetch().then(function() { | ||
assert.equal(m2.get("asd"),"das"); | ||
@@ -36,3 +18,11 @@ t(); | ||
}); | ||
it('should .destroy from store', function(t) { | ||
var m = new MyModel({id:1, "asd":"das"}); | ||
m.destroy() | ||
.then(function() { | ||
t(); | ||
}).otherwise(t); | ||
}); | ||
}); | ||
}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable and can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
49568
1629
70
0
7
1
18
1
+ Addedbackbone-db@~0.3.0
+ Addedbackbone-promises@~0.1.8
+ Addedwhen@~2.7.0
+ Addedbackbone@1.1.2(transitive)
+ Addedbackbone-db@0.3.4(transitive)
+ Addedbackbone-promises@0.1.8(transitive)
+ Addedjsonquery@0.1.8(transitive)
+ Addedlodash@2.4.2(transitive)
+ Addedunderscore@1.13.7(transitive)
+ Addedwhen@2.4.02.7.1(transitive)
- Removedbackbone-deferred@git+ssh://git@github.com/Applifier/backbone-deferred.git
- Removedbackbone@1.0.0(transitive)
Updatedbackbone@~1.1.0