// # Recline Backends // // Backends are connectors to backend data sources and stores // // This is just the base module containing a template Base class and convenience methods. this.recline = this.recline || {}; this.recline.Backend = this.recline.Backend || {}; (function($, my) { // ## Backbone.sync // // Override Backbone.sync to hand off to sync function in relevant backend Backbone.sync = function(method, model, options) { return model.backend.sync(method, model, options); }; // ## recline.Backend.Base // // Base class for backends providing a template and convenience functions. // You do not have to inherit from this class but even when not it does provide guidance on the functions you must implement. // // Note also that while this (and other Backends) are implemented as Backbone models this is just a convenience. my.Base = Backbone.Model.extend({ // ### sync // // An implementation of Backbone.sync that will be used to override // Backbone.sync on operations for Datasets and Documents which are using this backend. // // For read-only implementations you will need only to implement read method // for Dataset models (and even this can be a null operation). The read method // should return relevant metadata for the Dataset. We do not require read support // for Documents because they are loaded in bulk by the query method. // // For backends supporting write operations you must implement update and delete support for Document objects. // // All code paths should return an object conforming to the jquery promise API. sync: function(method, model, options) { }, // ### query // // Query the backend for documents returning them in bulk. This method will // be used by the Dataset.query method to search the backend for documents, // retrieving the results in bulk. // // @param {recline.model.Dataset} model: Dataset model. // // @param {Object} queryObj: object describing a query (usually produced by // using recline.Model.Query and calling toJSON on it). // // The structure of data in the Query object or // Hash should follow that defined in issue 34. // (Of course, if you are writing your own backend, and hence // have control over the interpretation of the query object, you // can use whatever structure you like). // // @returns {Promise} promise API object. The promise resolve method will // be called on query completion with a QueryResult object. // // A QueryResult has the following structure (modelled closely on // ElasticSearch - see this issue for more // details): // //
// {
// total: // (required) total number of results (can be null)
// hits: [ // (required) one entry for each result document
// {
// _score: // (optional) match score for document
// _type: // (optional) document type
// _source: // (required) document/row object
// }
// ],
// facets: { // (optional)
// // facet results (as per )
// }
// }
//
query: function(model, queryObj) {
},
// convenience method to convert simple set of documents / rows to a QueryResult
_docsToQueryResult: function(rows) {
var hits = _.map(rows, function(row) {
return { _source: row };
});
return {
total: null,
hits: hits
};
},
// ## _wrapInTimeout
//
// Convenience method providing a crude way to catch backend errors on JSONP calls.
// Many of backends use JSONP and so will not get error messages and this is
// a crude way to catch those errors.
_wrapInTimeout: function(ourFunction) {
var dfd = $.Deferred();
var timeout = 5000;
var timer = setTimeout(function() {
dfd.reject({
message: 'Request Error: Backend did not respond after ' + (timeout / 1000) + ' seconds'
});
}, timeout);
ourFunction.done(function(arguments) {
clearTimeout(timer);
dfd.resolve(arguments);
})
.fail(function(arguments) {
clearTimeout(timer);
dfd.reject(arguments);
})
;
return dfd.promise();
}
});
}(jQuery, this.recline.Backend));