[#128,backend/gdoc][s]: refactor gdocs to standard backend setup.

This commit is contained in:
Rufus Pollock
2012-05-26 17:46:51 +01:00
parent 5890007c59
commit e9d1b8a55a
2 changed files with 123 additions and 104 deletions

View File

@@ -1,7 +1,9 @@
this.recline = this.recline || {}; this.recline = this.recline || {};
this.recline.Backend = this.recline.Backend || {}; this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.GDocs = this.recline.Backend.GDocs || {};
(function($, my) { (function($, my) {
// ## Google spreadsheet backend // ## Google spreadsheet backend
// //
// Connect to Google Docs spreadsheet. // Connect to Google Docs spreadsheet.
@@ -16,50 +18,25 @@ this.recline.Backend = this.recline.Backend || {};
// 'gdocs' // 'gdocs'
// ); // );
// </pre> // </pre>
my.GDoc = my.Base.extend({ my.Backbone = function() {
__type__: 'gdoc', this.__type__ = 'gdocs';
readonly: true, this.readonly = true;
getUrl: function(dataset) {
var url = dataset.get('url'); this.sync = function(method, model, options) {
if (url.indexOf('feeds/list') != -1) {
return url;
} else {
// https://docs.google.com/spreadsheet/ccc?key=XXXX#gid=0
var regex = /.*spreadsheet\/ccc?.*key=([^#?&+]+).*/;
var matches = url.match(regex);
if (matches) {
var key = matches[1];
var worksheet = 1;
var out = 'https://spreadsheets.google.com/feeds/list/' + key + '/' + worksheet + '/public/values?alt=json';
return out;
} else {
alert('Failed to extract gdocs key from ' + url);
}
}
},
sync: function(method, model, options) {
var self = this; var self = this;
if (method === "read") { if (method === "read") {
var dfd = $.Deferred(); var dfd = $.Deferred();
var dataset = model; loadData(model.get('url')).done(function(result) {
model.fields.reset(result.fields);
var url = this.getUrl(model);
$.getJSON(url, function(d) {
result = self.gdocsToJavascript(d);
model.fields.reset(_.map(result.field, function(fieldId) {
return {id: fieldId};
})
);
// cache data onto dataset (we have loaded whole gdoc it seems!) // cache data onto dataset (we have loaded whole gdoc it seems!)
model._dataCache = result.data; model._dataCache = result.data;
dfd.resolve(model); dfd.resolve(model);
}); });
return dfd.promise(); return dfd.promise();
} }
}, };
query: function(dataset, queryObj) { this.query = function(dataset, queryObj) {
var dfd = $.Deferred(); var dfd = $.Deferred();
var fields = _.pluck(dataset.fields.toJSON(), 'id'); var fields = _.pluck(dataset.fields.toJSON(), 'id');
@@ -72,70 +49,115 @@ this.recline.Backend = this.recline.Backend || {};
}); });
return obj; return obj;
}); });
dfd.resolve(this._docsToQueryResult(objs)); var out = {
total: objs.length,
hits: _.map(objs, function(row) {
return { _source: row }
})
}
dfd.resolve(out);
return dfd; return dfd;
}, };
gdocsToJavascript: function(gdocsSpreadsheet) { };
/*
:options: (optional) optional argument dictionary:
columnsToUse: list of columns to use (specified by field names)
colTypes: dictionary (with column names as keys) specifying types (e.g. range, percent for use in conversion).
:return: tabular data object (hash with keys: field and data).
Issues: seems google docs return columns in rows in random order and not even sure whether consistent across rows. // ## loadData
*/ //
var options = {}; // loadData from a google docs URL
if (arguments.length > 1) { //
options = arguments[1]; // @return object with two attributes
} //
var results = { // * fields: array of objects
'field': [], // * data: array of arrays
'data': [] var loadData = function(url) {
}; var dfd = $.Deferred();
// default is no special info on type of columns var url = my.getSpreadsheetAPIUrl(url);
var colTypes = {}; var out = {
if (options.colTypes) { fields: [],
colTypes = options.colTypes; data: []
}
// either extract column headings from spreadsheet directly, or used supplied ones
if (options.columnsToUse) {
// columns set to subset supplied
results.field = options.columnsToUse;
} else {
// set columns to use to be all available
if (gdocsSpreadsheet.feed.entry.length > 0) {
for (var k in gdocsSpreadsheet.feed.entry[0]) {
if (k.substr(0, 3) == 'gsx') {
var col = k.substr(4);
results.field.push(col);
}
}
}
}
// converts non numberical values that should be numerical (22.3%[string] -> 0.223[float])
var rep = /^([\d\.\-]+)\%$/;
$.each(gdocsSpreadsheet.feed.entry, function (i, entry) {
var row = [];
for (var k in results.field) {
var col = results.field[k];
var _keyname = 'gsx$' + col;
var value = entry[_keyname]['$t'];
// if labelled as % and value contains %, convert
if (colTypes[col] == 'percent') {
if (rep.test(value)) {
var value2 = rep.exec(value);
var value3 = parseFloat(value2);
value = value3 / 100;
}
}
row.push(value);
}
results.data.push(row);
});
return results;
} }
}); $.getJSON(url, function(d) {
result = my.parseData(d);
result.fields = _.map(result.fields, function(fieldId) {
return {id: fieldId};
});
dfd.resolve(result);
});
return dfd.promise();
};
}(jQuery, this.recline.Backend)); // ## parseData
//
// Parse data from Google Docs API into a reasonable form
//
// :options: (optional) optional argument dictionary:
// columnsToUse: list of columns to use (specified by field names)
// colTypes: dictionary (with column names as keys) specifying types (e.g. range, percent for use in conversion).
// :return: tabular data object (hash with keys: field and data).
//
// Issues: seems google docs return columns in rows in random order and not even sure whether consistent across rows.
my.parseData = function(gdocsSpreadsheet) {
var options = {};
if (arguments.length > 1) {
options = arguments[1];
}
var results = {
'fields': [],
'data': []
};
// default is no special info on type of columns
var colTypes = {};
if (options.colTypes) {
colTypes = options.colTypes;
}
if (gdocsSpreadsheet.feed.entry.length > 0) {
for (var k in gdocsSpreadsheet.feed.entry[0]) {
if (k.substr(0, 3) == 'gsx') {
var col = k.substr(4);
results.fields.push(col);
}
}
}
// converts non numberical values that should be numerical (22.3%[string] -> 0.223[float])
var rep = /^([\d\.\-]+)\%$/;
$.each(gdocsSpreadsheet.feed.entry, function (i, entry) {
var row = [];
for (var k in results.fields) {
var col = results.fields[k];
var _keyname = 'gsx$' + col;
var value = entry[_keyname]['$t'];
// if labelled as % and value contains %, convert
if (colTypes[col] == 'percent') {
if (rep.test(value)) {
var value2 = rep.exec(value);
var value3 = parseFloat(value2);
value = value3 / 100;
}
}
row.push(value);
}
results.data.push(row);
});
return results;
};
// Convenience function to get GDocs JSON API Url from standard URL
my.getSpreadsheetAPIUrl = function(url) {
if (url.indexOf('feeds/list') != -1) {
return url;
} else {
// https://docs.google.com/spreadsheet/ccc?key=XXXX#gid=0
var regex = /.*spreadsheet\/ccc?.*key=([^#?&+]+).*/;
var matches = url.match(regex);
if (matches) {
var key = matches[1];
var worksheet = 1;
var out = 'https://spreadsheets.google.com/feeds/list/' + key + '/' + worksheet + '/public/values?alt=json';
return out;
} else {
alert('Failed to extract gdocs key from ' + url);
}
}
};
}(jQuery, this.recline.Backend.GDocs));

View File

@@ -273,8 +273,8 @@ var sample_gdocs_spreadsheet_data = {
"encoding": "UTF-8" "encoding": "UTF-8"
} }
test("GDoc Backend", function() { test("GDocs Backend", function() {
var backend = new recline.Backend.GDoc(); var backend = new recline.Backend.GDocs.Backbone();
var dataset = new recline.Model.Dataset({ var dataset = new recline.Model.Dataset({
url: 'https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json' url: 'https://spreadsheets.google.com/feeds/list/0Aon3JiuouxLUdDQwZE1JdV94cUd6NWtuZ0IyWTBjLWc/od6/public/values?alt=json'
}, },
@@ -301,13 +301,10 @@ test("GDoc Backend", function() {
$.getJSON.restore(); $.getJSON.restore();
}); });
test("GDoc Backend.getUrl", function() { test("GDocs Backend.getUrl", function() {
var key = 'Abc_dajkdkjdafkj'; var key = 'Abc_dajkdkjdafkj';
var dataset = new recline.Model.Dataset({ var url = 'https://docs.google.com/spreadsheet/ccc?key=' + key + '#gid=0'
url: 'https://docs.google.com/spreadsheet/ccc?key=' + key + '#gid=0' var out = recline.Backend.GDocs.getSpreadsheetAPIUrl(url);
});
var backend = new recline.Backend.GDoc();
var out = backend.getUrl(dataset);
var exp = 'https://spreadsheets.google.com/feeds/list/' + key + '/1/public/values?alt=json' var exp = 'https://spreadsheets.google.com/feeds/list/' + key + '/1/public/values?alt=json'
equal(exp, out); equal(exp, out);
}); });