Jump To …

backend.ckan.js

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

We need 2 things to make most requests:

  1. CKAN API endpoint
  2. ID of resource for which request is being made

There are 2 ways to specify this information.

EITHER (checked in order):

  • Every dataset must have an id equal to its resource id on the CKAN instance
  • The dataset has an endpoint attribute pointing to the CKAN API endpoint

OR:

Set the url attribute of the dataset to point to the Resource on the CKAN instance. The endpoint and id will then be automatically computed.

  my.__type__ = 'ckan';

Default CKAN API endpoint used for requests (you can change this but it will affect every request!)

DEPRECATION: this will be removed in v0.7. Please set endpoint attribute on dataset instead

  my.API_ENDPOINT = 'http://datahub.io/api';

fetch

  my.fetch = function(dataset) {
    if (dataset.endpoint) {
      var wrapper = my.DataStore(dataset.endpoint);
    } else {
      var out = my._parseCkanResourceUrl(dataset.url);
      dataset.id = out.resource_id;
      var wrapper = my.DataStore(out.endpoint);
    }
    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();
  };

only put in the module namespace so we can access for tests!

  my._normalizeQuery = function(queryObj, dataset) {
    var actualQuery = {
      resource_id: dataset.id,
      q: queryObj.q,
      limit: queryObj.size || 10,
      offset: queryObj.from || 0
    };
    if (queryObj.sort && queryObj.sort.length > 0) {
      var _tmp = _.map(queryObj.sort, function(sortObj) {
        return sortObj.field + ' ' + (sortObj.order || '');
      });
      actualQuery.sort = _tmp.join(',');
    }
    return actualQuery;
  }

  my.query = function(queryObj, dataset) {
    if (dataset.endpoint) {
      var wrapper = my.DataStore(dataset.endpoint);
    } else {
      var out = my._parseCkanResourceUrl(dataset.url);
      dataset.id = out.resource_id;
      var wrapper = my.DataStore(out.endpoint);
    }
    var actualQuery = my._normalizeQuery(queryObj, dataset);
    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 = that.endpoint + '/3/action/datastore_search';
      var jqxhr = $.ajax({
        url: searchUrl,
        data: data,
        dataType: 'json'
      });
      return jqxhr;
    }

    return that;
  };

Parse a normal CKAN resource URL and return API endpoint etc

Normal URL is something like http://demo.ckan.org/dataset/some-dataset/resource/eb23e809-ccbb-4ad1-820a-19586fc4bebd

  my._parseCkanResourceUrl = function(url) {
    parts = url.split('/');
    var len = parts.length;
    return {
      resource_id: parts[len-1],
      endpoint: parts.slice(0,[len-4]).join('/') + '/api'
    }
  };

  var CKAN_TYPES_MAP = {
    'int4': 'integer',
    'int8': 'integer',
    'float8': 'float'
  };

}(jQuery, this.recline.Backend.Ckan));