diff --git a/src/model.js b/src/model.js index 34ee4c1b..81c25efb 100644 --- a/src/model.js +++ b/src/model.js @@ -13,37 +13,31 @@ this.recline.Model = this.recline.Model || {}; my.Dataset = Backbone.Model.extend({ __type__: 'Dataset', initialize: function(model, backend) { + _.bindAll(this, 'query'); this.backend = backend; if (backend && backend.constructor == String) { this.backend = my.backends[backend]; } this.currentDocuments = new my.DocumentList(); this.docCount = null; - this.defaultQuery = { - size: 100 - , offset: 0 - }; - // this.queryState = {}; + this.queryState = new my.Query(); + this.queryState.bind('change', this.query); }, - // ### getDocuments + // ### query // - // AJAX method with promise API to get rows (documents) from the backend. + // AJAX method with promise API to get documents from the backend. + // + // It will query based on current query state (given by this.queryState) + // updated by queryObj (if provided). // // Resulting DocumentList are used to reset this.currentDocuments and are // also returned. - // - // :param numRows: passed onto backend getDocuments. - // :param start: passed onto backend getDocuments. - // - // this does not fit very well with Backbone setup. Backbone really expects you to know the ids of objects your are fetching (which you do in classic RESTful ajax-y world). But this paradigm does not fill well with data set up we have here. - // This also illustrates the limitations of separating the Dataset and the Backend query: function(queryObj) { var self = this; - this.queryState = queryObj || this.defaultQuery; - this.queryState = _.extend({size: 100, offset: 0}, this.queryState); + this.queryState.set(queryObj, {silent: true}); var dfd = $.Deferred(); - this.backend.query(this, this.queryState).done(function(rows) { + this.backend.query(this, this.queryState.toJSON()).done(function(rows) { var docs = _.map(rows, function(row) { var _doc = new my.Document(row); _doc.backend = self.backend; @@ -79,6 +73,13 @@ my.DocumentList = Backbone.Collection.extend({ model: my.Document }); +my.Query = Backbone.Model.extend({ + defaults: { + size: 100 + , offset: 0 + } +}); + // ## Backend registry // // Backends will register themselves by id into this registry diff --git a/test/model.test.js b/test/model.test.js index d44ff330..e8c2edab 100644 --- a/test/model.test.js +++ b/test/model.test.js @@ -1,68 +1,91 @@ (function ($) { module("Dataset"); -test('Memory Backend', function () { - var datasetId = 'test-dataset'; - var inData = { - metadata: { - title: 'My Test Dataset' - , name: '1-my-test-dataset' - , id: datasetId - , headers: ['x', 'y', 'z'] - }, - documents: [ - {id: 0, x: 1, y: 2, z: 3} - , {id: 1, x: 2, y: 4, z: 6} - , {id: 2, x: 3, y: 6, z: 9} - , {id: 3, x: 4, y: 8, z: 12} - , {id: 4, x: 5, y: 10, z: 15} - , {id: 5, x: 6, y: 12, z: 18} - ] - }; +var memoryData = { + metadata: { + title: 'My Test Dataset' + , name: '1-my-test-dataset' + , id: 'test-dataset' + , headers: ['x', 'y', 'z'] + }, + documents: [ + {id: 0, x: 1, y: 2, z: 3} + , {id: 1, x: 2, y: 4, z: 6} + , {id: 2, x: 3, y: 6, z: 9} + , {id: 3, x: 4, y: 8, z: 12} + , {id: 4, x: 5, y: 10, z: 15} + , {id: 5, x: 6, y: 12, z: 18} + ] +}; + +function makeBackendDataset() { var backend = new recline.Model.BackendMemory(); - backend.addDataset(inData); - var dataset = new recline.Model.Dataset({id: datasetId}, backend); - // ### Start testing - expect(10); - // convenience for tests - var data = backend.datasets[datasetId]; + backend.addDataset(memoryData); + var dataset = new recline.Model.Dataset({id: memoryData.metadata.id}, backend); + return dataset; +} + +test('Memory Backend: basics', function () { + var dataset = makeBackendDataset(); + expect(3); + // convenience for tests - get the data that should get changed + var data = dataset.backend.datasets[memoryData.metadata.id]; dataset.fetch().then(function(datasetAgain) { equal(dataset.get('name'), data.metadata.name); deepEqual(dataset.get('headers'), data.metadata.headers); equal(dataset.docCount, 6); - var queryObj = { - size: 4 - , offset: 2 - }; - dataset.query(queryObj).then(function(documentList) { - deepEqual(data.documents[2], documentList.models[0].toJSON()); - }); - var queryObj = { - sort: [ - ['y', 'desc'] - ] - }; - dataset.query(queryObj).then(function(docs) { - var doc0 = dataset.currentDocuments.models[0].toJSON(); - equal(doc0.x, 6); - }); - dataset.query().then(function(docList) { - equal(docList.length, Math.min(100, data.documents.length)); - var doc1 = docList.models[0]; - deepEqual(doc1.toJSON(), data.documents[0]); + }); +}); - // Test UPDATE - var newVal = 10; - doc1.set({x: newVal}); - doc1.save().then(function() { - equal(data.documents[0].x, newVal); - }) +test('Memory Backend: query', function () { + var dataset = makeBackendDataset(); + // convenience for tests - get the data that should get changed + var data = dataset.backend.datasets[memoryData.metadata.id]; + var dataset = makeBackendDataset(); + var queryObj = { + size: 4 + , offset: 2 + }; + dataset.query(queryObj).then(function(documentList) { + deepEqual(data.documents[2], documentList.models[0].toJSON()); + }); +}); - // Test Delete - doc1.destroy().then(function() { - equal(data.documents.length, 5); - equal(data.documents[0].x, inData.documents[1].x); - }); +test('Memory Backend: query sort', function () { + var dataset = makeBackendDataset(); + // convenience for tests - get the data that should get changed + var data = dataset.backend.datasets[memoryData.metadata.id]; + var queryObj = { + sort: [ + ['y', 'desc'] + ] + }; + dataset.query(queryObj).then(function(docs) { + var doc0 = dataset.currentDocuments.models[0].toJSON(); + equal(doc0.x, 6); + }); +}); + +test('Memory Backend: update and delete', function () { + var dataset = makeBackendDataset(); + // convenience for tests - get the data that should get changed + var data = dataset.backend.datasets[memoryData.metadata.id]; + dataset.query().then(function(docList) { + equal(docList.length, Math.min(100, data.documents.length)); + var doc1 = docList.models[0]; + deepEqual(doc1.toJSON(), data.documents[0]); + + // Test UPDATE + var newVal = 10; + doc1.set({x: newVal}); + doc1.save().then(function() { + equal(data.documents[0].x, newVal); + }) + + // Test Delete + doc1.destroy().then(function() { + equal(data.documents.length, 5); + equal(data.documents[0].x, memoryData.documents[1].x); }); }); });