Skip to content

Instantly share code, notes, and snippets.

@aaronj1335
Last active August 29, 2015 13:57
Show Gist options
  • Select an option

  • Save aaronj1335/9769565 to your computer and use it in GitHub Desktop.

Select an option

Save aaronj1335/9769565 to your computer and use it in GitHub Desktop.
waterfall data layer
define([
'underscore',
'knockout'
], function(_, ko) {
function Collection() {
}
Collection.prototype.init = function() {
this._instances = ko.observableArray();
};
// to be overridden:
// - Collection.prototype.url
// - Collection.prototype.create
// - Collection.prototype.update
Collection.prototype._dedupe = function(item) {
var existing = this.byId(item.id);
if (!existing) {
existing = this.create(item);
this._instances.push(existing);
} else {
this.update(existing, item);
}
return existing;
};
Collection.prototype.byId = function(id) {
return _.find(this._instances(), function(instance) {
return instance.id() === id;
});
};
Collection.prototype.fetch = function(params) {
// the specific thing we're using for the ajax request should maybe be
// abstracted
return $.ajax(_.extend({
url: this.url
}, params))
.then(function(result) {
result.forEach(this._dedupe.bind(this));
return result;
});
};
Collection.prototype.fetchOne = function(id, params) {
return $.ajax(_.extend({
url: this._url + '/' + id
}, params))
.then(function(item) {
return this._dedupe(item);
});
};
// also need to figure out saving and deleting. two options:
// - add them as methods to Collection.prototype (uglier)
// - add them as methods to the items in resource._instances, but then we
// need a way of updating that list when an item is saved or deleted
return Collection;
});
define([
'ko',
'waterfall',
'collection'
], function(ko, waterfall, Collection) {
var instance;
function MetadataCollection() {
this.init();
}
MetadataCollection.prototype = new Collection();
MetadataCollection.prototype.url = waterfall.metadata.url;
// this is where things get weird. we probably want to return an instance of
// something w/ a 'save' and 'delete' method, but those instances need some
// way of notifying the Collection instance when they're deleted or saved for
// the first time so the Collection can update its _instances OA accordingly
//
// so basically like a Record class
MetadataCollection.prototype.create = function(item) {
return {
id: ko.observable(item.id),
name: ko.observable(item.name),
multiValue: ko.observable(item.multiValue),
format: ko.observable(item.format)
};
};
MetadataCollection.prototype.update = function(existing, item) {
existing.id(item.id);
existing.name(item.name);
existing.multiValue(item.multiValue);
existing.format(item.format);
};
// use an accessor function, since we'll usually just want a single shared
// app-wide Collection of MetadataCollection, but we want to be able to reset
// that instance for stuff like unit testing
//
// the "singleton pattern", or "object manager factory get instance function"
function accessor() {
return instance? instance : instance = new MetadataCollection();
}
accessor.MetadataCollection = MetadataCollection;
accessor.reset = function() {
instance = null;
};
return accessor;
});
@evanrmurphy
Copy link

Really productive talk today @aaronj1335! ๐Ÿ‘ Some notes:

  • Queries aren't computed observable arrays, but each one has an underlying (non-computed) observable array
  • Collections and queries each have their own observable array, but they share model instances
  • When a query calls the server, it gets updated with the appropriate model instances. The collection corresponding to that type of model also gets updated. If those model instances aren't in the collection yet, they're added. If they are in the collection, then they're updated with the new data from the server.
  • Collections aren't bootstrapped at the initial page load. They just grow organically throughout the session as queries are made to the server.
  • Computed array observables aren't needed for the initial implementation of this data layer
  • Queries can be created, refreshed and deleted, but they can't be changed to different types of queries (queries with different parameters)

This stuff is feeling much more clear to me now. Planning to sketch out some code and/or detailed examples soon.

@evanrmurphy
Copy link

Now for the fun part: what should we name this little library we're developing? ๐Ÿ˜„ Knockout Data? Boxing Gloves? (Because you wouldn't want to knock someone out without boxing gloves!)

@evanrmurphy
Copy link

Started a branch for this called "data-layer" in WaterfallEngineering/frontend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment