Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added update functionality #153

Merged
merged 5 commits into from
May 22, 2017
Merged
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"deep-equal": "^1.0.1",
"es6-promise": "^4.0.5",
"is-my-json-valid": "^2.16.0",
"modifyjs": "^0.3.1",
"object-path": "0.11.4",
"pouchdb-core": "6.2.0",
"pouchdb-find": "6.2.0",
Expand Down
12 changes: 12 additions & 0 deletions src/RxCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,18 @@ class RxCollection {
}
}

/**
* updates an object with a mongolike syntax
* @param {object} queryObj
* @param {object} updateObj
*/

async update(queryObj, updateObj) {
const docs = await this.find(queryObj).exec();
for (let doc of docs)
await doc.update(updateObj);
}

/**
* takes a mongoDB-query-object and returns the documents
* @param {object} queryObj
Expand Down
28 changes: 28 additions & 0 deletions src/RxDocument.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import clone from 'clone';
import objectPath from 'object-path';
import deepEqual from 'deep-equal';
import modify from 'modifyjs';

import * as util from './util';
import * as RxChangeEvent from './RxChangeEvent';
Expand Down Expand Up @@ -250,6 +251,33 @@ class RxDocument {
return this;
};

/**
* updates document
* @param {object} updateObj
*/
async update(updateObj) {
const newDoc = modify(this._data, updateObj);

Object.keys(this._data).forEach((previousPropName) => {
if (newDoc[previousPropName]) {
// if we don't check inequality, it triggers an update attempt on fields that didn't really change,
// which causes problems with "readonly" fields
if (!deepEqual(this[previousPropName], newDoc[previousPropName]))
this[previousPropName] = newDoc[previousPropName];

} else
delete this[previousPropName];

});
delete newDoc._rev;
delete newDoc._id;
Object.keys(newDoc).forEach(newPropName => {
if (!deepEqual(this[newPropName], newDoc[newPropName]))
this[newPropName] = newDoc[newPropName];
});
await this.save();
}

/**
* save document if its data has changed
* @return {boolean} false if nothing to save
Expand Down
17 changes: 17 additions & 0 deletions src/RxQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,23 @@ class RxQuery {
return docs;
}

/**
* updates all found documents
* @param {object} updateObj
* @return {Promise(RxDocument|RxDocument[])} promise with updated documents
*/
async update(updateObj) {
const docs = await this.exec();
if (Array.isArray(docs)) {
await Promise.all(
docs.map(doc => doc.update(updateObj))
);
} else {
// via findOne()
await docs.update(updateObj);
}
return docs;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could possibly extract this and remove to a common function, it's very similar (the only two differences are the "action" (.update vs .remove) and the fact that update takes an argument)

Up to you - some people like to apply a rule of three :)


async exec() {
return await this.$
Expand Down
19 changes: 19 additions & 0 deletions test/unit/RxCollection.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,15 @@ describe('RxCollection.test.js', () => {
});
});
});
describe('.update()', () => {
it('should update all documents matched by a query', async() => {
const c = await humansCollection.create();
await c.update({}, {$set: {firstName: 'new first name'}});
const docs = await c.find().exec();
for (let doc of docs)
assert.equal(doc._data.firstName, 'new first name');
});
});
describe('.find()', () => {
describe('find all', () => {
describe('positive', () => {
Expand Down Expand Up @@ -798,6 +807,16 @@ describe('RxCollection.test.js', () => {
assert.equal(docsAfter.length, 9);
});
});
describe('.update()', () => {
it('should update all documents', async() => {
const c = await humansCollection.create(10);
const query = c.find();
const updated = await query.update({$set: {firstName: 'new first name'}});
const docsAfterUpdate = await c.find().exec();
for (let doc of docsAfterUpdate)
assert.equal(doc._data.firstName, 'new first name');
});
});
});
describe('.findOne()', () => {
describe('positive', () => {
Expand Down
21 changes: 21 additions & 0 deletions test/unit/RxDocument.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,27 @@ describe('RxDocument.test.js', () => {
});
});
});
describe('update', () => {
it('a value with a mongo like query', async() => {
const c = await humansCollection.createPrimary(1);
const doc = await c.findOne().exec();
await doc.update({$set: {firstName: 'new first name'}});
const updatedDoc = await c.findOne({firstName: 'new first name'}).exec();
assert.equal(updatedDoc.firstName, 'new first name');
});

it('unset a value', async() => {
const c = await humansCollection.createPrimary(1);
const doc = await c.findOne().exec();
await doc.update({
$unset: {
firstName: ''
}
});
const updatedDoc = await c.findOne().exec();
assert.equal(updatedDoc.firstName, undefined);
});
});
describe('pseudo-Proxy', () => {
describe('get', () => {
it('top-value', async() => {
Expand Down