Skip to content

Commit

Permalink
FIX #791 auto-bind methods of RxDocument to the instance
Browse files Browse the repository at this point in the history
  • Loading branch information
pubkey committed Sep 11, 2018
1 parent 1a1765d commit 2ea5a7e
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Features:
- Added `RxReplicationState.denied$` [#763](https://github.com/pubkey/rxdb/issues/763)
- Added option for CORS to server-plugin
- `this`-scope of collection-hooks are bound to the collection itself [#788](https://github.com/pubkey/rxdb/issues/788)
- All methods of `RxDocument` are bound to the instance [#791](https://github.com/pubkey/rxdb/issues/791)

Bugfixes:
- checkAdapter doesn't cleanup test databases [#714](https://github.com/pubkey/rxdb/issues/714)
Expand Down
4 changes: 4 additions & 0 deletions docs-src/rx-document.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,10 @@ myDocument.name = 'foobar';
await myDocument.save(); // submit the changes to the storage
```

## NOTICE: All methods of RxDocument are bound to the instance

When you get a method from a `RxDocument`, the method is automatically bound to the documents instance. This means you do not have to use things like `myMethod.bind(myDocument)` like you would do in jsx.


### isRxDocument
Returns true if the given object is an instance of RxDocument. Returns false if not.
Expand Down
22 changes: 17 additions & 5 deletions src/rx-collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,23 @@ export class RxCollection {
const props = Object.getOwnPropertyNames(obj);
props.forEach(key => {
const desc = Object.getOwnPropertyDescriptor(obj, key);
desc.enumerable = false;
desc.configurable = false;
if (desc.writable)
desc.writable = false;
Object.defineProperty(proto, key, desc);
if (typeof desc.value === 'function') {
// when getting a function, we automatically do a .bind(this)
Object.defineProperty(proto, key, {
get() {
return desc.value.bind(this);
},
enumerable: false,
configurable: false
});

} else {
desc.enumerable = false;
desc.configurable = false;
if (desc.writable)
desc.writable = false;
Object.defineProperty(proto, key, desc);
}
});
});

Expand Down
67 changes: 67 additions & 0 deletions test/unit/orm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,71 @@ config.parallel('orm.test.js', () => {
});
});
});
describe('ISSUES', () => {
it('#791 Document methods are not bind() to the document', async () => {
const db = await RxDB.create({
name: util.randomCouchString(),
adapter: 'memory',
multiInstance: false
});

const schema = {
version: 0,
type: 'object',
primaryPath: '_id',
properties: {
name: {
type: 'string'
},
nested: {
type: 'object',
properties: {
foo: {
type: 'string'
}
}
}
}
};

const collection = await db.collection({
name: 'person',
schema: schema,
methods: {
hello: function() {
return this.name;
}
}
});

const doc = await collection.insert({
name: 'hi',
nested: {
foo: 'bar'
}
});

// orm-method
const hello = doc.hello;
assert.equal(hello(), 'hi');

// prototype-method
const get = doc.get;
assert.equal(get('name'), 'hi');

// nested
const nestedObj = doc.nested;
assert.equal(nestedObj.foo, 'bar');

// nested getter-method
const obs = nestedObj.foo$;
const emitted = [];
const sub = obs.subscribe(v => emitted.push(v));
await AsyncTestUtil.waitUntil(() => emitted.length === 1);
assert.equal(emitted[0], 'bar');
sub.unsubscribe();

db.destroy();
});
});
});

0 comments on commit 2ea5a7e

Please sign in to comment.