Skip to content

Commit

Permalink
Merge pull request #38 from dhritzkiv/options
Browse files Browse the repository at this point in the history
Add options to fetchById and getOrFetch
  • Loading branch information
wraithgar committed Jan 15, 2016
2 parents 1f695cb + 8d6684a commit 312db77
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 45 deletions.
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ npm install ampersand-collection-rest-mixin
## api

##### create(model, options)

Create a new instance of a model in this collection. Add the model to the collection immediately.

###### options

- `wait` - default: `false`. If set to true, we wait for the server to agree before updating the collection.

##### fetch(options)

Fetch the default set of models for this collection, and set them onto this collection.

###### options
Expand All @@ -30,14 +32,24 @@ Fetch the default set of models for this collection, and set them onto this coll
- `set` [boolean] - defaut: `true`. When left true, executes the `reset` method on the collection with server response. When set to false, the collection will *not be modified* after the HTTP request is complete. This enables use of of the collection strictly as an API client. The `success` and `error` handlers are still triggered. Useful in rare circumstances.
- `success(collection, response, options)` [function] - default: `undefined`. Called after the XHR has completed successfully and the collection is updated.
- `error(model, response, options)` [function] - default: `undefined`. Called after the XHR has failed.
- `always(err, response, body)` [function] - default: `undefined`. Called when request finishes no matter what the result.

##### fetchById(id, options, cb)

##### fetchById(id, cb)
fetches a model and adds it to collection when fetched

##### getOrFetch(id, options, cb)

get or fetch a model by id

###### options

same options as `fetch()`, with the addition of:

- `all` [boolean] - default: `false`. If `true`, this fetches the entire collection and then returns the requested model.

##### sync()

proxy to [ampersand-sync](AmpersandJS/ampersand-sync)

## example
Expand Down
101 changes: 57 additions & 44 deletions ampersand-collection-rest-mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,30 @@
var sync = require('ampersand-sync');
var assign = require('lodash.assign');

// Wrap an optional error callback with a fallback error event.
var wrapError = function(model, options) {
var error = options.error;
options.error = function(resp) {
if (error) error(model, resp, options);
model.trigger('error', model, resp, options);
};
};

module.exports = {
// Fetch the default set of models for this collection, resetting the
// collection when they arrive. If `reset: true` is passed, the response
// data will be passed through the `reset` method instead of `set`.
fetch: function(options) {
options = options ? assign({}, options) : {};
if (options.parse === void 0) options.parse = true;
var self = this;

var success = options.success;
var collection = this;
options.success = function(resp) {
var method = options.reset ? 'reset' : 'set';
if (options.set !== false) collection[method](resp, options);
if (success) success(collection, resp, options);
if (options.set !== false) collection.trigger('sync', collection, resp, options);
if (options.set !== false) self[method](resp, options);
if (success) success(self, resp, options);
if (options.set !== false) self.trigger('sync', self, resp, options);
};

// Wrap an optional error callback with a fallback error event.
var error = options.error;
options.error = function(resp) {
if (error) error(self, resp, options);
self.trigger('error', self, resp, options);
};
wrapError(this, options);

var request = this.sync('read', this, options);
// Make the request available on the options object so it can be accessed
// further down the line by `parse`, sync listeners, etc
Expand All @@ -42,10 +41,10 @@ module.exports = {
options = options ? assign({}, options) : {};
if (!(model = this._prepareModel(model, options))) return false;
if (!options.wait) this.add(model, options);
var collection = this;
var self = this;
var success = options.success;
options.success = function(model, resp) {
if (options.wait) collection.add(model, options);
if (options.wait) self.add(model, options);
if (success) success(model, resp, options);
};
model.save(null, options);
Expand All @@ -62,50 +61,64 @@ module.exports = {
cb = options;
options = {};
}

var self = this;
var model = this.get(id);

if (model) {
return window.setTimeout(function() {
return cb(null, model);
}, 0);
}
function done() {
var model = self.get(id);
if (model) {
if (cb) cb(null, model);
} else {
cb(new Error('not found'));
}
return window.setTimeout(cb.bind(null, null, model), 0);
}

if (options.all) {
options.success = done;
options.error = done;
//preserve original `options.always`
var always = options.always;
options.always = function(err, resp, body) {
if (always) always(err, resp, body);
if (!cb) return;

var model = self.get(id);
var err2 = model ? null : new Error('not found');
cb(err2, model);
};
return this.fetch(options);
} else {
return this.fetchById(id, cb);
return this.fetchById(id, options, cb);
}
},

// fetchById: fetches a model and adds it to
// collection when fetched.
fetchById: function (id, cb) {
fetchById: function (id, options, cb) {
if (arguments.length !== 3) {
cb = options;
options = {};
}

var self = this;
var idObj = {};
idObj[this.mainIndex] = id;
var model = new this.model(idObj, {collection: this});
return model.fetch({
success: function () {
model = self.add(model);
if (cb) cb(null, model);
},
error: function (collection, resp) {
delete model.collection;
if (cb) {
var error = new Error(resp.statusText);
error.status = resp.status;
cb(error);
}

//preserve original `options.success`
var success = options.success;
options.success = function (resp) {
model = self.add(model);
if (success) success(self, resp, options);
if (cb) cb(null, model);
};

//preserve original `options.error`
var error = options.error;
options.error = function (collection, resp) {
delete model.collection;
if (error) error(collection, resp, options);
if (cb) {
var err = new Error(resp.statusText);
err.status = resp.status;
cb(err);
}
});
};

return model.fetch(options);
}
};

0 comments on commit 312db77

Please sign in to comment.