Merge branch '217-ckan-backend'

This commit is contained in:
Rufus Pollock 2012-08-18 02:08:53 +01:00
commit f06df0d5df
3 changed files with 254 additions and 0 deletions

88
src/backend.ckan.js Normal file
View File

@ -0,0 +1,88 @@
this.recline = this.recline || {};
this.recline.Backend = this.recline.Backend || {};
this.recline.Backend.Ckan = this.recline.Backend.Ckan || {};
(function($, my) {
// ## CKAN Backend
//
// This provides connection to the CKAN DataStore (v2)
//
// General notes
//
// * Every dataset must have an id equal to its resource id on the CKAN instance
// * You should set the CKAN API endpoint for requests by setting API_ENDPOINT value on this module (recline.Backend.Ckan.API_ENDPOINT)
my.__type__ = 'ckan';
// Default CKAN API endpoint used for requests (you can change this but it will affect every request!)
my.API_ENDPOINT = 'http://datahub.io/api';
// ### fetch
my.fetch = function(dataset) {
var wrapper = my.DataStore();
var dfd = $.Deferred();
var jqxhr = wrapper.search({resource_id: dataset.id, limit: 0});
jqxhr.done(function(results) {
// map ckan types to our usual types ...
var fields = _.map(results.result.fields, function(field) {
field.type = field.type in CKAN_TYPES_MAP ? CKAN_TYPES_MAP[field.type] : field.type;
return field;
});
var out = {
fields: fields,
useMemoryStore: false
};
dfd.resolve(out);
});
return dfd.promise();
};
my.query = function(dataset, queryObj) {
var wrapper = my.DataStore(dataset.url);
var actualQuery = {
resource_id: dataset.id,
q: queryObj.q,
limit: queryObj.size,
offset: queryObj.from
};
var dfd = $.Deferred();
var jqxhr = wrapper.search(actualQuery);
jqxhr.done(function(results) {
var out = {
total: results.result.total,
hits: results.result.records,
};
dfd.resolve(out);
});
return dfd.promise();
};
// ### DataStore
//
// Simple wrapper around the CKAN DataStore API
//
// @param endpoint: CKAN api endpoint (e.g. http://datahub.io/api)
my.DataStore = function(endpoint) {
var that = {
endpoint: endpoint || my.API_ENDPOINT
};
that.search = function(data) {
var searchUrl = my.endpoint + '/3/action/datastore_search';
var jqxhr = $.ajax({
url: searchUrl,
data: data,
dataType: 'json'
});
return jqxhr;
}
return that;
}
var CKAN_TYPES_MAP = {
'int4': 'integer',
'float8': 'float',
'text': 'string'
};
}(jQuery, this.recline.Backend.Ckan));

164
test/backend.ckan.test.js Normal file
View File

@ -0,0 +1,164 @@
module("Backend CKAN");
test("fetch", function() {
var dataset = new recline.Model.Dataset({
url: 'http://localhost:5000/dataset/test-data-viewer/resource/4f1299ab-a100-4e5f-ba81-e6d234a2f3bd',
backend: 'ckan'
});
var stub = sinon.stub($, 'ajax', function(options) {
if (options.url.indexOf('datastore_search') != -1) {
return {
done: function(callback) {
callback(sample_data);
return this;
},
fail: function() {
}
};
}
});
dataset.fetch().done(function(dataset) {
deepEqual(
_.pluck(dataset.fields.toJSON(), 'id'),
_.pluck(sample_data.result.fields, 'id')
);
// check we've mapped types correctly
equal(dataset.fields.get('x').get('type'), 'integer');
equal(dataset.fields.get('country').get('type'), 'string');
// fetch does a query so we can check for records
equal(dataset.recordCount, 6);
equal(dataset.records.length, 6);
equal(dataset.records.at(0).get('id'), 0);
equal(dataset.records.at(0).get('country'), 'DE');
});
$.ajax.restore();
});
var sample_data = {
"help": "",
"result": {
"fields": [
{
"id": "_id",
"type": "int4"
},
{
"id": "id",
"type": "int4"
},
{
"id": "date",
"type": "date"
},
{
"id": "x",
"type": "int4"
},
{
"id": "y",
"type": "int4"
},
{
"id": "z",
"type": "int4"
},
{
"id": "country",
"type": "text"
},
{
"id": "title",
"type": "text"
},
{
"id": "lat",
"type": "float8"
},
{
"id": "lon",
"type": "float8"
}
],
"records": [
{
"_id": 1,
"country": "DE",
"date": "2011-01-01",
"id": 0,
"lat": 52.56,
"lon": 13.4,
"title": "first",
"x": 1,
"y": 2,
"z": 3
},
{
"_id": 2,
"country": "UK",
"date": "2011-02-02",
"id": 1,
"lat": 54.97,
"lon": -1.6,
"title": "second",
"x": 2,
"y": 4,
"z": 24
},
{
"_id": 3,
"country": "US",
"date": "2011-03-03",
"id": 2,
"lat": 40.0,
"lon": -75.5,
"title": "third",
"x": 3,
"y": 6,
"z": 9
},
{
"_id": 4,
"country": "UK",
"date": "2011-04-04",
"id": 3,
"lat": 57.27,
"lon": -6.2,
"title": "fourth",
"x": 4,
"y": 8,
"z": 6
},
{
"_id": 5,
"country": "UK",
"date": "2011-05-04",
"id": 4,
"lat": 51.58,
"lon": 0.0,
"title": "fifth",
"x": 5,
"y": 10,
"z": 15
},
{
"_id": 6,
"country": "DE",
"date": "2011-06-02",
"id": 5,
"lat": 51.04,
"lon": 7.9,
"title": "sixth",
"x": 6,
"y": 12,
"z": 18
}
],
"resource_id": "4f1299ab-a100-4e5f-ba81-e6d234a2f3bd",
"total": 6
},
"success": true
};

View File

@ -36,6 +36,7 @@
<script type="text/javascript" src="../src/backend.gdocs.js"></script>
<script type="text/javascript" src="../src/backend.elasticsearch.js"></script>
<script type="text/javascript" src="../src/backend.csv.js"></script>
<script type="text/javascript" src="../src/backend.ckan.js"></script>
<script type="text/javascript" src="model.test.js"></script>
<script type="text/javascript" src="backend.memory.test.js"></script>
@ -43,6 +44,7 @@
<script type="text/javascript" src="backend.gdocs.test.js"></script>
<script type="text/javascript" src="backend.elasticsearch.test.js"></script>
<script type="text/javascript" src="backend.csv.test.js"></script>
<script type="text/javascript" src="backend.ckan.test.js"></script>
<!-- views and view tests -->
<script type="text/javascript" src="../src/view.grid.js"></script>