Skip to content

Commit

Permalink
v2: Move from blanket save to precise patch!
Browse files Browse the repository at this point in the history
  • Loading branch information
aseemk committed Jun 12, 2015
1 parent bbf8e86 commit 18c3e11
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 26 deletions.
60 changes: 38 additions & 22 deletions models/user.js
Expand Up @@ -25,35 +25,58 @@ Object.defineProperty(User.prototype, 'id', {
});

Object.defineProperty(User.prototype, 'name', {
get: function () {
return this._node.properties['name'];
},
set: function (name) {
this._node.properties['name'] = name;
}
get: function () { return this._node.properties['name']; }
});

// private helpers:

// takes the given caller-provided properties (which corresponding to our public
// instance properties), selects only whitelisted ones for editing, validates
// them, and translates them to the corresponding internal db properties.
function translate(props) {
// today, the only property we have is `name`; it's the same; and it needs
// no validation. (might want to validate things like length, Unicode, etc.)
return {
name: props.name,
};
}

// public instance methods:

// TODO: node-neo4j v2 is no longer has a `save` method, because updates should
// be atomic and precise via Cypher, so consider a `patch` method instead.
User.prototype.save = function (callback) {
// atomically updates this user, both locally and remotely in the db, with the
// given property updates.
User.prototype.patch = function (props, callback) {
var safeProps = translate(props);

var query = [
'MATCH (user:User)',
'WHERE ID(user) = {id}',
'SET user = {props}',
].join('\n')
'SET user += {props}',
'RETURN user',
].join('\n');

var params = {
id: this.id,
props: this._node.properties,
props: safeProps,
};

var self = this;

db.cypher({
query: query,
params: params,
}, function (err) {
callback(err);
}, function (err, results) {
if (err) return callback(err);

if (!results.length) {
err = new Error('User has been deleted! ID: ' + self.id);
return callback(err);
}

// Update our node with this updated+latest data from the server:
self._node = results[0]['user'];

callback(null);
});
};

Expand Down Expand Up @@ -211,20 +234,13 @@ User.getAll = function (callback) {

// creates the user and persists (saves) it to the db, incl. indexing it:
User.create = function (props, callback) {
// select and translate the given public-facing properties into the
// database-internal properties we persist.
// today, the only property we have is `name`, and it's the same.
var props = {
name: props.name,
};

var query = [
'CREATE (user:User {props})',
'RETURN user',
].join('\n');

var params = {
props: props
props: translate(props)
};

db.cypher({
Expand Down
3 changes: 1 addition & 2 deletions routes/users.js
Expand Up @@ -51,8 +51,7 @@ exports.show = function (req, res, next) {
exports.edit = function (req, res, next) {
User.get(req.params.id, function (err, user) {
if (err) return next(err);
user.name = req.body['name'];
user.save(function (err) {
user.patch(req.body, function (err) {
if (err) return next(err);
res.redirect('/users/' + user.id);
});
Expand Down
5 changes: 3 additions & 2 deletions test/models/user.js
Expand Up @@ -191,8 +191,9 @@ describe('User models:', function () {
});

it('Update user A', function (next) {
USER_A.name += ' (edited)';
USER_A.save(function (err) {
USER_A.patch({
name: USER_A.name + ' (edited)',
}, function (err) {
return next(err);
});
});
Expand Down

0 comments on commit 18c3e11

Please sign in to comment.