Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

More work on Riak adapter, basic CRUD and tests

  • Loading branch information...
commit a5b882701efdca9918c3f387b5f1b4ac70d4332e 1 parent 3d4b36a
mde authored
View
190 lib/adapters/riak/index.js
@@ -0,0 +1,190 @@
+var utils = require('utilities')
+ , request = utils.request
+ , BaseAdapter = require('../base_adapter').BaseAdapter
+ , _baseConfig
+ , _bucketizeModelName;
+
+_baseConfig = {
+ protocol: 'http'
+, host: 'localhost'
+, port: 8098
+};
+
+var Adapter = function (options) {
+ var opts = options || {}
+ , config;
+
+ this.name = 'riak';
+ this.config = _baseConfig;
+ this.client = null;
+
+ utils.mixin(this.config, opts);
+
+ this.init.apply(this, arguments);
+};
+
+Adapter.prototype = new BaseAdapter();
+Adapter.prototype.constructor = Adapter;
+
+_bucketizeModelName = function (name) {
+ var bucketName = utils.inflection.pluralize(name);
+ bucketName = utils.string.snakeize(bucketName);
+ return bucketName;
+};
+
+utils.mixin(Adapter.prototype, new (function () {
+
+ this.init = function () {
+ };
+
+ this.request = function (options, callback) {
+ var opts = options || {}
+ , config = this.config;
+ request({
+ method: opts.method || 'GET'
+ , url: config.protocol + '://' + config.host + ':' + config.port +
+ '/riak/' + opts.url
+ , data: opts.data || null
+ , dataType: 'json'
+ , headers: {
+ 'Content-Type': 'application/json'
+ }
+ }, callback);
+ };
+
+ this.load = function (query, callback) {
+ var bucket = _bucketizeModelName(query.model.modelName)
+ , id = query.byId
+ , requestOpts;
+
+ // Single instance-lookup by id
+ if (id) {
+ requestOpts = {
+ url: bucket + '/' + id
+ , method: 'GET'
+ };
+ this.request(requestOpts, function (err, data) {
+ var inst
+ , res = [];
+ if (err) {
+ if (err.statusCode == 404) {
+ callback(null, null);
+ }
+ else {
+ callback(err, null);
+ }
+ }
+ else {
+ inst = query.model.create(data);
+ inst.id = id;
+ inst._saved = true;
+ res.push(inst);
+ // If explicitly limited to one, just return the single instance
+ // This is also used by the `first` method
+ if (query.opts.limit == 1) {
+ res = res[0];
+ }
+ callback(null, res);
+ }
+ });
+ }
+ // Teh mapreducy
+ else {
+ callback(new Error('Complex queries not supported'), null);
+ }
+ };
+
+ this.update = function (data, query, opts, callback) {
+ var bucket = _bucketizeModelName(query.model.modelName)
+ , id = query.byId
+ , requestOpts
+ , item = data;
+ // Single instance-lookup by id
+ if (id) {
+ // Bail out if instance isn't valid
+ if (!item.isValid()) {
+ return callback(data.errors, null);
+ }
+
+ item = item.toData();
+ item = JSON.stringify(item);
+
+ requestOpts = {
+ url: bucket + '/' + id
+ , method: 'PUT'
+ , data: item
+ };
+
+ this.request(requestOpts, function (err, data) {
+ if (err) {
+ callback(err, null);
+ }
+ else {
+ // FIXME: What is the right data to return here? Right now this
+ // is basically overwriting a doc, but we might be supporting
+ // bulk-updates at some point
+ callback(null, true);
+ }
+ });
+ }
+ // Bulk update?
+ else {
+ callback(new Error('Bulk update is not supported'), null);
+ }
+ };
+
+ this.remove = function (query, opts, callback) {
+ var bucket = _bucketizeModelName(query.model.modelName)
+ , id = query.byId
+ , requestOpts;
+
+ // Single instance-lookup by id
+ if (id) {
+ requestOpts = {
+ url: bucket + '/' + id
+ , method: 'DELETE'
+ };
+ this.request(requestOpts, function (err, data) {
+ var inst
+ , res = [];
+ if (err) {
+ callback(err, null);
+ }
+ else {
+ callback(null, true);
+ }
+ });
+ }
+ // Teh mapreducy
+ else {
+ callback(new Error('Bulk remove is not supported'), null);
+ }
+ };
+
+ this.insert = function (data, opts, callback) {
+ var self = this
+ , item = data
+ , bucket = _bucketizeModelName(item.type)
+ , id = utils.string.uuid()
+ , url = bucket + '/' + id
+ , requestOpts;
+
+ item.id = id;
+ item = item.toData();
+ item = JSON.stringify(item);
+
+ requestOpts = {
+ url: url
+ , method: 'POST'
+ , data: item
+ };
+ this.request(requestOpts, callback);
+ };
+
+ // May need to set bucket props here?
+ this.createTable = function (names, callback) {};
+
+})());
+
+module.exports.Adapter = Adapter;
+
View
15 lib/adapters/sql/postgres.js
@@ -118,11 +118,6 @@ utils.mixin(Adapter.prototype, new (function () {
, updates = []
, update;
- // Bail out if instance isn't valid
- if (!data.isValid()) {
- return callback(data.errors, null);
- }
-
// Iterate over the properties in the params, make sure each
// property exists in the definition
for (var p in data) {
@@ -149,13 +144,15 @@ utils.mixin(Adapter.prototype, new (function () {
callback(err, null);
}
else {
- data._saved = true;
- callback(null, data);
+ // FIXME: What is the right data to return here? SQL updates
+ // can affect lots of rows, and I don't think we want to limit
+ // it to single-item updates
+ callback(null, true);
}
});
};
- this.remove = function (query, callback) {
+ this.remove = function (query, opts, callback) {
var sql = '';
sql += 'DELETE FROM ' + this._tableizeModelName(query.model.modelName) + ' ';
sql += 'WHERE ' + this._serializeConditions(query.conditions);
@@ -165,7 +162,7 @@ utils.mixin(Adapter.prototype, new (function () {
callback(err, null);
}
else {
- callback(null, data);
+ callback(null, true);
}
});
};
View
9 lib/index.js
@@ -124,7 +124,7 @@ utils.mixin(model, new (function () {
};
/**
- @name ModelBase#updateAttributes
+ @name ModelBase#updateProperties
@public
@function
@description Updates the attributes an instance of a Geddy
@@ -137,10 +137,11 @@ utils.mixin(model, new (function () {
@param {String} [opts.locale=null] Optional locale for
localizing error messages from validations
*/
- this.updateAttributes = function (params, opts) {
+ this.updateProperties = function (params, opts) {
model.updateItem(this, params, opts || {});
};
-
+ // TODO: Deprecate?
+ this.updateAttributes = this.updateProperties;
/**
@name ModelBase#toData
@public
@@ -439,7 +440,7 @@ utils.mixin(model, new (function () {
throw new Error('Adapter not found for ' + name);
}
- return adapt.remove.apply(adapt, [query, callback]);
+ return adapt.remove.apply(adapt, [query, opts, callback]);
};
obj.modelName = name;
View
94 test/adapters/riak/index.js
@@ -0,0 +1,94 @@
+var utils = require('utilities')
+ , model = require('../../../lib')
+ , Adapter = require('../../../lib/adapters/riak').Adapter
+ , Query = require('../../../lib/query/query').Query
+ , generator = require('../../../lib/generators/sql')
+ , adapter
+ , assert = require('assert')
+ , currentId
+ , tests
+ , testItems = []
+ , Zooby = require('../../fixtures/zooby').Zooby
+ , User = require('../../fixtures/user').User
+ , Profile = require('../../fixtures/profile').Profile
+ , Account = require('../../fixtures/account').Account;
+
+tests = {
+ 'before': function () {
+ adapter = new Adapter();
+
+ model.adapters = {
+ 'Zooby': adapter
+ , 'User': adapter
+ , 'Profile': adapter
+ , 'Account': adapter
+ };
+ }
+
+, 'test create adapter': function () {
+ assert.ok(adapter instanceof Adapter);
+ }
+
+, 'test save new, string UUID id': function (next) {
+ var z = Zooby.create({foo: 'FOO'});
+ z.save(function (err, data) {
+ if (err) {
+ throw err;
+ }
+ currentId = z.id;
+ next();
+ });
+ }
+
+, 'test first via string id': function (next) {
+ Zooby.first(currentId, {}, function (err, data) {
+ if (err) {
+ throw err;
+ }
+ assert.equal(data.id, currentId);
+ next();
+ });
+ }
+
+, 'test save existing': function (next) {
+ Zooby.first(currentId, {}, function (err, data) {
+ if (err) {
+ throw err;
+ }
+ var inst = data;
+ data.updateProperties({
+ foo: 'BAR'
+ });
+ inst.save(function (err, data) {
+ if (err) {
+ throw err;
+ }
+ Zooby.first(currentId, {}, function (err, data) {
+ if (err) {
+ throw err;
+ }
+ assert.equal(data.foo, 'BAR');
+ next();
+ });
+ });
+ });
+ }
+
+, 'test remove': function (next) {
+ Zooby.remove(currentId, {}, function (err, data) {
+ if (err) {
+ throw err;
+ }
+ Zooby.first(currentId, {}, function (err, data) {
+ if (err) {
+ throw err;
+ }
+ assert.ok(!data);
+ next();
+ });
+ });
+ }
+
+};
+
+module.exports = tests;
View
15 test/adapters/sql/postgres.js
@@ -236,14 +236,19 @@ tests = {
}
, 'test save existing': function (next) {
- Zooby.first({id: currentId}, {}, function (err, data) {
+ Zooby.first(currentId, {}, function (err, data) {
+ if (err) {
+ throw err;
+ }
var inst = data;
- inst.foo = 'BAR';
+ data.updateProperties({
+ foo: 'BAR'
+ });
inst.save(function (err, data) {
if (err) {
throw err;
}
- Zooby.first({id: currentId}, {}, function (err, data) {
+ Zooby.first(currentId, {}, function (err, data) {
if (err) {
throw err;
}
@@ -255,11 +260,11 @@ tests = {
}
, 'test remove': function (next) {
- Zooby.remove({id: currentId}, {}, function (err, data) {
+ Zooby.remove(currentId, {}, function (err, data) {
if (err) {
throw err;
}
- Zooby.first({id: currentId}, {}, function (err, data) {
+ Zooby.first(currentId, {}, function (err, data) {
if (err) {
throw err;
}
Please sign in to comment.
Something went wrong with that request. Please try again.