Skip to content

Commit

Permalink
.fetch() now returns an array (#333)
Browse files Browse the repository at this point in the history
Fixes #332
  • Loading branch information
deontologician committed May 9, 2016
1 parent ce6d45e commit 2a5d769
Show file tree
Hide file tree
Showing 21 changed files with 89 additions and 112 deletions.
21 changes: 8 additions & 13 deletions GETTING-STARTED.md
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,12 @@ To retrieve messages from the collection we use [`.fetch`][fetch]. In this case,

```js
chat.fetch().forEach(
// Each result from the chat collection
// will pass through this function
(item) => {
console.log(item);
(items) => {
items.forEach((item) => {
// Each result from the chat collection
// will pass through this function
console.log(item);
})
},
// If an error occurs, this function
// will execute with the `err` message
Expand All @@ -287,13 +289,6 @@ chat.fetch().forEach(
})
```

Each document of the result `.forEach` will pass individually through the result handler as the results are emitted from the server. If you'd rather handle the entire results array at once, you can add [`.toArray()`][toArray] after [`.fetch()`][fetch] like so:

```js
chat.fetch().toArray().forEach((completeArrayOfResults) => {})
```


### Removing documents

To remove documents from a collection, you can use either [`.remove`][remove] or [`.removeAll`][removeAll]:
Expand Down Expand Up @@ -378,8 +373,8 @@ let chats = [];
// Retrieve all messages from the server
const retrieveMessages = () => {
chat.order('datetime')
// fetch all results as an array, rather than one at a time
.fetch().toArray()
// fetch all results as an array
.fetch()
// Retrieval successful, update our model
.forEach((newChats) => {
chats = chats.concat(newChats);
Expand Down
33 changes: 5 additions & 28 deletions client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,31 +175,15 @@ the query request.

```js

// Returns the entire contents of the collection
// Returns the entire contents of the collection as an array
horizon('chats').fetch().forEach(
result => console.log('Result:', result),
results => console.log('Results:', results),
err => console.error(err),
() => console.log('Results fetched, query done!')
)

// Sample output
// Result: { id: 1, chat: 'Hey there' }
// Result: { id: 2, chat: 'Ho there' }
// Results fetched, query done!
```

If you would rather get the results all at once as an array, you can
chain `.toArray()` to the call:

```js
horizon('chats').fetch().toArray().forEach(
results => console.log('All results: ', results),
err => console.error(err),
() => console.log('Results fetched, query done!')
)

// Sample output
// All results: [ { id: 1, chat: 'Hey there' }, { id: 2, chat: 'Ho there' } ]
// Results: [{ id: 1, chat: 'Hey there' }, { id: 2, chat: 'Ho there' }]
// Results fetched, query done!
```

Expand Down Expand Up @@ -239,16 +223,9 @@ Means of providing handlers to a query on a Horizon collection.
When `.forEach` is chained off of a read operation it accepts three functions as parameters. A results handler, a error handler, and a result completion handler.

```js
// Documents are returned one at a time.
// Documents are returned as an array
chats.fetch().forEach(
(result) => { console.log("A single document =>" + result ) },
(error) => { console.log ("Danger Will Robinson 🤖! || " + error ) },
() => { console.log("Read is now complete" ) }
);

// To wait and retrieve all documents as a single array instead of immediately one at a time.
chats.fetch().toArray().forEach(
(result) => { console.log("A single document =>" + result ) },
(result) => { console.log("All documents =>" + result ) },
(error) => { console.log ("Danger Will Robinson 🤖! || " + error ) },
() => { console.log("Read is now complete" ) }
);
Expand Down
8 changes: 7 additions & 1 deletion client/src/ast.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { publishReplay } from 'rxjs/operator/publishReplay'
import { scan } from 'rxjs/operator/scan'
import { filter } from 'rxjs/operator/filter'
import { map } from 'rxjs/operator/map'
import { toArray } from 'rxjs/operator/toArray'

import snakeCase from 'snake-case'

Expand Down Expand Up @@ -53,7 +54,12 @@ class TermBase {
// array with all results. An observable is returned which will
// lazily emit the query when subscribed to
fetch() {
return this._sendRequest('query', this._query)
const raw = this._sendRequest('query', this._query)
if (this._query.find) {
return raw
} else {
return raw::toArray()
}
}
findAll(...fieldValues) {
this::checkIfLegalToChain('findAll')
Expand Down
16 changes: 8 additions & 8 deletions client/test/above.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const aboveSuite = window.aboveSuite = (getData) => () => {

// By default `above` is closed
it('is a closed bound by default', assertCompletes(() =>
data.order('id').above({ id: 5 }).fetch()::toArray()
data.order('id').above({ id: 5 }).fetch()
::tap(res => assert.deepEqual(res, [
{ id: 5, a: 60 },
{ id: 6, a: 50 },
Expand All @@ -19,7 +19,7 @@ const aboveSuite = window.aboveSuite = (getData) => () => {

// We can also pass that explicitly
it('allows "closed" to be passed explicitly', assertCompletes(() =>
data.order('id').above({ id: 5 }, 'closed').fetch()::toArray()
data.order('id').above({ id: 5 }, 'closed').fetch()
::tap(res => assert.deepEqual(res, [
{ id: 5, a: 60 },
{ id: 6, a: 50 },
Expand All @@ -29,19 +29,19 @@ const aboveSuite = window.aboveSuite = (getData) => () => {
// But we can make it open
it('can return an open bounded result', assertCompletes(() =>
data.order('id').above({ id: 5 }, 'open').fetch()
::tap(res => assert.deepEqual(res, { id: 6, a: 50 }))
::tap(([ res ]) => assert.deepEqual(res, { id: 6, a: 50 }))
))

// Let's try something that returns no values
it('returns no results if bound eliminates all documents',
assertCompletes(() =>
data.order('id').above({ id: 7 }).fetch()
::tap(() => assert.fail())
::tap(res => assert.deepEqual(res, []))
))

// We can chain `above` off a collection
it('can be chained from a collection directly', assertCompletes(() =>
data.above({ id: 5 }).fetch()::toArray()
data.above({ id: 5 }).fetch()
::tap(res => {
assert.isArray(res)
assert.lengthOf(res, 2)
Expand All @@ -50,7 +50,7 @@ const aboveSuite = window.aboveSuite = (getData) => () => {

// Or off other things
it('can be chained from a findAll', assertCompletes(() =>
data.findAll({ a: 20 }).above({ id: 3 }).fetch()::toArray()
data.findAll({ a: 20 }).above({ id: 3 }).fetch()
::tap(res => {
assert.isArray(res)
assert.lengthOf(res, 2)
Expand All @@ -64,7 +64,7 @@ const aboveSuite = window.aboveSuite = (getData) => () => {

// Let's try it on a non-primary key
it('can be used on a non-primary key', assertCompletes(() =>
data.order([ 'a', 'id' ]).above({ a: 20 }).fetch()::toArray()
data.order([ 'a', 'id' ]).above({ a: 20 }).fetch()
::tap(res => assert.deepEqual(res, [
{ id: 2, a: 20, b: 1 },
{ id: 3, a: 20, b: 2 },
Expand All @@ -76,7 +76,7 @@ const aboveSuite = window.aboveSuite = (getData) => () => {

// Let's try it on a non-primary key, but open
it('can be used on non-primary key with open bound', assertCompletes(() =>
data.order([ 'a', 'id' ]).above({ a: 20 }, 'open').fetch()::toArray()
data.order([ 'a', 'id' ]).above({ a: 20 }, 'open').fetch()
::tap(res => assert.deepEqual(res, [
{ id: 6, a: 50 },
{ id: 5, a: 60 },
Expand Down
2 changes: 1 addition & 1 deletion client/test/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe('Core API tests', () => {
before(assertCompletes(() =>
data.store(testData)
::ignoreElements()
::concat(data.fetch()::toArray())
::concat(data.fetch())
::tap(res => assert.sameDeepMembers(res, testData))
))

Expand Down
16 changes: 8 additions & 8 deletions client/test/below.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const belowSuite = window.belowSuite = (getData) => () => {

// By default `below` is open
it('defaults to open', assertCompletes(() =>
data.order('id').below({ id: 3 }).fetch()::toArray()
data.order('id').below({ id: 3 }).fetch()
::tap(res => assert.deepEqual(res, [
{ id: 1, a: 10 },
{ id: 2, a: 20, b: 1 }
Expand All @@ -19,7 +19,7 @@ const belowSuite = window.belowSuite = (getData) => () => {

// We can also pass that explicitly
it('can be explicitly set to be an open bound', assertCompletes(() =>
data.order('id').below({ id: 3 }, 'open').fetch()::toArray()
data.order('id').below({ id: 3 }, 'open').fetch()
::tap(res => assert.deepEqual(res, [
{ id: 1, a: 10 },
{ id: 2, a: 20, b: 1 },
Expand All @@ -28,7 +28,7 @@ const belowSuite = window.belowSuite = (getData) => () => {

// But we can make it closed
it('can be explicitly set to be a closed bound', assertCompletes(() =>
data.order('id').below({ id: 3 }, 'closed').fetch()::toArray()
data.order('id').below({ id: 3 }, 'closed').fetch()
::tap(res => assert.deepEqual(res, [
{ id: 1, a: 10 },
{ id: 2, a: 20, b: 1 },
Expand All @@ -39,12 +39,12 @@ const belowSuite = window.belowSuite = (getData) => () => {
// Let's try something that returns no values
it('can return no values', assertCompletes(() =>
data.order('id').below({ id: 0 }).fetch()
::tap(() => assert.fail())
::tap(res => assert.deepEqual(res, []))
))

// We can chain `below` off a collection
it('can be chained off of a collection', assertCompletes(() =>
data.below({ id: 3 }).fetch()::toArray()
data.below({ id: 3 }).fetch()
::tap(res => {
assert.isArray(res)
assert.lengthOf(res, 2)
Expand All @@ -53,7 +53,7 @@ const belowSuite = window.belowSuite = (getData) => () => {

// Or off other things
it('can be chained off of a findAll term', assertCompletes(() =>
data.findAll({ a: 20 }).below({ id: 4 }).fetch()::toArray()
data.findAll({ a: 20 }).below({ id: 4 }).fetch()
::tap(res => {
assert.isArray(res)
assert.lengthOf(res, 2)
Expand All @@ -68,12 +68,12 @@ const belowSuite = window.belowSuite = (getData) => () => {
// Let's try it on a non-primary index
it('can bound a non-primary index', assertCompletes(() =>
data.order([ 'a', 'id' ]).below({ a: 20 }).fetch()
::tap(res => assert.deepEqual(res, { id: 1, a: 10 }))
::tap(([ res ]) => assert.deepEqual(res, { id: 1, a: 10 }))
))

// Let's try it on a non-primary key, but closed
it('can closed bound a non-primary key', assertCompletes(() =>
data.order([ 'a', 'id' ]).below({ a: 20 }, 'closed').fetch()::toArray()
data.order([ 'a', 'id' ]).below({ a: 20 }, 'closed').fetch()
::tap(res => assert.deepEqual(res, [
{ id: 1, a: 10 },
{ id: 2, a: 20, b: 1 },
Expand Down
10 changes: 5 additions & 5 deletions client/test/chaining.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const chainingSuite = window.chainingSuite = getData => () => {
.order('id')
.above({ id: 2 })
.below({ id: 4 })
.fetch()::toArray()
.fetch()
::tap(res => assert.deepEqual(res, [
{ id: 2, a: 20, b: 1 },
{ id: 3, a: 20, b: 2 },
Expand All @@ -27,7 +27,7 @@ const chainingSuite = window.chainingSuite = getData => () => {
.below({ id: 4 })
.above({ id: 2 })
.order('id', 'descending')
.fetch()::toArray()
.fetch()
::tap(res => assert.deepEqual(res, [
{ id: 3, a: 20, b: 2 },
{ id: 2, a: 20, b: 1 },
Expand All @@ -39,7 +39,7 @@ const chainingSuite = window.chainingSuite = getData => () => {
data.findAll({ a: 20 })
.above({ id: 2 })
.order('id').below({ id: 4 }).limit(1)
.fetch()::toArray()
.fetch()
::tap(res => assert.deepEqual(res, [ { id: 2, a: 20, b: 1 } ]))
))

Expand All @@ -49,7 +49,7 @@ const chainingSuite = window.chainingSuite = getData => () => {
.order('id')
.above({ id: 2 })
.limit(1)
.fetch()::toArray()
.fetch()
::tap(res => assert.deepEqual(res, [ { id: 2, a: 20, b: 1 } ]))
))

Expand All @@ -60,7 +60,7 @@ const chainingSuite = window.chainingSuite = getData => () => {
.above({ id: 2 })
.below({ id: 4 }, 'closed')
.limit(2)
.fetch()::toArray()
.fetch()
::tap(res => assert.deepEqual(res, [
{ id: 2, a: 20, b: 1 },
{ id: 3, a: 20, b: 2 },
Expand Down
4 changes: 2 additions & 2 deletions client/test/collection.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ const collectionSuite = window.collectionSuite = (getHorizon, getData, getTestDa

// Grab everything from the collection.
it('allows getting all values from the collection', assertCompletes(() =>
data.fetch()::toArray()
data.fetch()
::tap(res => assert.sameDeepMembers(testData, res))
))

// Reading from an empty collection should result in an empty array
it('returns an empty array from an empty collection', assertCompletes(() =>
empty_collection.fetch()::toArray()
empty_collection.fetch()
::tap(res => assert.sameDeepMembers(res, []))
))
} // Testing full collection reads
5 changes: 2 additions & 3 deletions client/test/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,10 @@ const findSuite = window.findSuite = getData => () => {

// Let's try this again, now with multiple results.
it('returns one result even if several documents match', assertCompletes(() =>
data.find({ a: 20 }).fetch()::toArray()
data.find({ a: 20 }).fetch()
// The id should be one of 2, 3, or 4
::tap(res => {
assert.include([ 2, 3, 4 ], res[0].id)
assert.equal(res.length, 1)
assert.include([ 2, 3, 4 ], res.id)
})
))

Expand Down
Loading

0 comments on commit 2a5d769

Please sign in to comment.