Skip to content

Commit

Permalink
ADD #165 postCreate-hook
Browse files Browse the repository at this point in the history
  • Loading branch information
pubkey committed Jun 3, 2017
1 parent f7c3d19 commit 08a00fb
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 14 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 4.X.X ()

Features:
-Added `postCreate`-[hook](https://pubkey.github.io/rxdb/Middleware.html#postCreate) [#165](https://github.com/pubkey/rxdb/issues/165)

Bugfixes:
- QueryCache returns old RxQuery when `.regex()` is used [#190](https://github.com/pubkey/rxdb/issues/190)
- `RxDocument.resync()` was broken [174](https://github.com/pubkey/rxdb/issues/174)
Expand Down
24 changes: 23 additions & 1 deletion docs-src/Middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ RxDB supports the following hooks:
- postSave
- preRemove
- postRemove
- postCreate


### Why is there no validate-hook?
Different to mongoose, the validation on document-data is running on the field-level for every change to a document.
This means if you set the value ```lastName``` of a RxDocument, then the validation will only run on the changed field, not the whole document.
Therefore it is not usefull to have validate-hooks when a document is written to the database.


## Use Cases
Middleware are useful for atomizing model logic and avoiding nested blocks of async code.
Here are some other ideas:
Expand Down Expand Up @@ -207,6 +208,27 @@ myCollection.postRemove(function(doc){
}, false);
```

### postCreate
This hook is called whenever a `RxDocument` is constructed.
You can use `postCreate` to modify every RxDocument-instance of the collection.
This adds a flexible way to add specifiy behavior to every document. You can also use it to add custom getter/setter to documents.


```js
myCollection.postCreate(function(doc){
Object.defineProperty(doc, 'myField', {
get: () => 'foobar',
});
}, true);

const doc = await myCollection.findOne().exec();

console.log(doc.myField);
// 'foobar'
```

Notice: This hook does not run on already created or cached documents. Make sure to add `postCreate`-hooks before interacting with the collection.


---------
If you are new to RxDB, you should continue [here](./ORM.md)
17 changes: 8 additions & 9 deletions src/RxCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { RxSchema } from './RxSchema';
import { RxDatabase } from './RxDatabase';

const HOOKS_WHEN = ['pre', 'post'];
const HOOKS_KEYS = ['insert', 'save', 'remove'];
const HOOKS_KEYS = ['insert', 'save', 'remove', 'create'];

class RxCollection {
constructor(database, name, schema, pouchSettings = {}, migrationStrategies = {}, methods = {}) {
Expand Down Expand Up @@ -191,28 +191,27 @@ class RxCollection {
});
}
/**
* @return {RxDocument}
* @return {Promise<RxDocument>}
*/
_createDocument(json) {

async _createDocument(json) {
// return from cache if exsists
const id = json[this.schema.primaryPath];
const cacheDoc = this._docCache.get(id);
if (cacheDoc) return cacheDoc;

const doc = RxDocument.create(this, json);
this._assignMethodsToDocument(doc);

this._docCache.set(id, doc);
await this._runHooks('post', 'create', doc);

return doc;
}
/**
* create RxDocument from the docs-array
* @return {RxDocument[]} documents
* @return {Promise<RxDocument[]>} documents
*/
_createDocuments(docsJSON) {
return docsJSON.map(json => this._createDocument(json));
async _createDocuments(docsJSON) {
return Promise.all(docsJSON.map(json => this._createDocument(json)));
}


Expand Down Expand Up @@ -250,7 +249,7 @@ class RxCollection {

json[this.schema.primaryPath] = insertResult.id;
json._rev = insertResult.rev;
const newDoc = this._createDocument(json);
const newDoc = await this._createDocument(json);

await this._runHooks('post', 'insert', newDoc);

Expand Down
8 changes: 4 additions & 4 deletions src/RxQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class RxQuery {
if (!Array.isArray(changeResult) && changeResult) this._mustReExec = true;
if (Array.isArray(changeResult) && !deepEqual(changeResult, this._resultsData)) {
ret = true;
this._setResultData(changeResult);
await this._setResultData(changeResult);
}

} catch (e) {
Expand All @@ -135,7 +135,7 @@ class RxQuery {
this._latestChangeEvent = latestAfter;
if (!deepEqual(newResultData, this._resultsData)) {
ret = true;
this._setResultData(newResultData);
await this._setResultData(newResultData);
}
}

Expand All @@ -145,9 +145,9 @@ class RxQuery {
return ret;
}

_setResultData(newResultData) {
async _setResultData(newResultData) {
this._resultsData = newResultData;
const newResults = this.collection._createDocuments(this._resultsData);
const newResults = await this.collection._createDocuments(this._resultsData);
this._results$.next(newResults);
}

Expand Down
2 changes: 2 additions & 0 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ declare class RxCollection {
postInsert(fun: Function, parallel: boolean): void;
postSave(fun: Function, parallel: boolean): void;
postRemove(fun: Function, parallel: boolean): void;
postCreate(fun: Function, parallel: boolean): void;


// migration
migrationNeeded(): Promise<boolean>;
Expand Down
25 changes: 25 additions & 0 deletions test/unit/Hooks.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,31 @@ describe('Hooks.test.js', () => {
describe('negative', () => {});
});
});
describe('postCreate', () => {
it('should define a getter', async() => {
const db = await RxDatabase.create({
name: util.randomCouchString(10),
adapter: 'memory',
multiInstance: true
});
const collection = await db.collection({
name: 'myhumans',
schema: schemas.primaryHuman
});
collection.postCreate(function(doc) {
Object.defineProperty(doc, 'myField', {
get: () => 'foobar',
});
}, false);

const human = schemaObjects.simpleHuman();
await collection.insert(human);
const doc = await collection.findOne().exec();
assert.equal('foobar', doc.myField);

db.destroy();
});
});
describe('issues', () => {
it('BUG #158 : Throwing error in async preInsert does not prevent insert', async() => {
const c = await humansCollection.create(0);
Expand Down

0 comments on commit 08a00fb

Please sign in to comment.