endpoint book

refactoring showaction.getRelated: async
This commit is contained in:
Meutel 2014-01-22 22:08:21 +01:00
parent 8839e5fb3a
commit a609d80de3
6 changed files with 123 additions and 26 deletions

View File

@ -3,8 +3,9 @@
"debugLevel":"debug", "debugLevel":"debug",
"endpoints": { "endpoints": {
"library":"endpoint/library.js", "library":"endpoint/library.js",
"book":"endpoint/book.js",
"author":"endpoint/author.js" "author":"endpoint/author.js"
}, },
"urlPrefix": "http://127.0.0.1:8080/bouquins", "urlPrefix": "http://127.0.0.1:8080",
"dbfile": "/home/meutel/metadata.db" "dbfile": "/home/meutel/metadata.db"
} }

View File

@ -108,17 +108,19 @@ ShowAction.prototype = Object.create(Action.prototype, {
logger.debug('resource loaded: ' + res); logger.debug('resource loaded: ' + res);
//TODO err //TODO err
var link = ''; var link = '';
var rels = self.getRelated(res); // { type: 'author', path: '/author/id'} var rels = self.getRelated(res, function(err, rels) {
logger.debug(rels); //TODO err
rels.forEach(function (e) { logger.debug(rels);
if (link.length > 0) link+=', '; rels.forEach(function (e) {
link += '<' + config.urlPrefix + e.path + '>; rel=' + e.type; if (link.length > 0) link+=', ';
}); link += '<' + config.urlPrefix + e.path + '>; rel=' + e.type;
var headers = {}; });
if (link.length > 0) { var headers = {};
headers.Link = link; if (link.length > 0) {
} headers.Link = link;
callback(null, 200, headers); }
callback(null, 200, headers);
}); // { type: 'author', path: '/author/id'}
}); });
} else { } else {
//TODO error? //TODO error?
@ -140,11 +142,11 @@ ShowAction.prototype = Object.create(Action.prototype, {
/** /**
* Get related resources. * Get related resources.
* @param res resource * @param res resource
* @return related resources { type: 'author', path: '/author/id'} * @param callback <function(err, rels)> related resources { type: 'author', path: '/author/id'}
*/ */
getRelated: { getRelated: {
value: function(res){ value: function(res, callback){
return []; callback(null, []);
}, enumerable: true, configurable: true, writable: true }, enumerable: true, configurable: true, writable: true
}, },

View File

@ -11,25 +11,31 @@ function Author() {
Author.prototype = Object.create(Endpoint.prototype, { Author.prototype = Object.create(Endpoint.prototype, {
bind: { bind: {
value: function(action, callback) { value: function(action, params, callback) {
switch (action.name) { switch (action.name) {
case 'show': case 'show':
action.resId = this.authorId; action.resId = this.authorId;
//TODO related action.getRelated = function(res, relcback){
action.loadResource = function(resId, callback) { // books of this autor
// TODO authors writing same book
relcback(null, new Array({ type: 'books', path: '/books?author='+this.resId }));
};
action.loadResource = function(resId, loadcback) {
logger.debug('loading author ' + resId); logger.debug('loading author ' + resId);
db.get('SELECT * FROM authors WHERE id = '+ resId, function(err, row) { db.get('SELECT * FROM authors WHERE id = '+ resId, function(err, row) {
callback(err, row); loadcback(err, row);
}); });
}; };
callback(null, action); callback(null, action);
break; break;
case 'list': case 'list':
//TODO related
action.loadResources = function(onload, onend) { action.loadResources = function(onload, onend) {
var query = 'SELECT * FROM authors LIMIT ? OFFSET ?'; var query = 'SELECT * FROM authors ';
if (!this.perPage) this.perPage = 30; if (!this.perPage) this.perPage = 30;
//TODO sanitize //TODO sanitize
if (!this.page) this.page = 0; if (!this.page) this.page = 0;
query += ' LIMIT ? OFFSET ?';
db.each(query, this.perPage, this.page*this.perPage, function (err, row) { db.each(query, this.perPage, this.page*this.perPage, function (err, row) {
onload(err, row); onload(err, row);
}, function(err) { }, function(err) {

88
lib/endpoint/book.js Normal file
View File

@ -0,0 +1,88 @@
/**
* Endpoint book.
*/
var Endpoint = require('./endpoint.js');
function Book() {
Endpoint.call(this);
this.bookId = null;
}
Book.prototype = Object.create(Endpoint.prototype, {
bind: {
value: function(action, params, callback) {
switch (action.name) {
case 'show':
action.resId = this.bookId;
action.getRelated = function(res,relcback){
var rels = new Array();
var nbrels = 3; // number of requests for rel
// call callback when no more requests running
var endrels = function(err) {
nbrels--;
if (err) logger.error(err);
if (nbrels == 0) relcback(null, rels);
};
var raq = 'SELECT * FROM books_authors_link WHERE book = ?';
db.each(raq, res.id, function (err, row) {
if (!err && row.author)
rels.push({ type: 'author', path: '/author/'+row.author });
}, endrels);
var rsq = 'SELECT * FROM books_series_link WHERE book = ?';
db.each(rsq, res.id, function (err, row) {
if (!err && row.series)
rels.push({ type: 'serie', path: '/serie/'+row.series });
}, endrels);
var rtq = 'SELECT * FROM books_tags_link WHERE book = ?';
db.each(rtq, res.id, function (err, row) {
if (!err && row.tag)
rels.push({ type: 'tag', path: '/tag/'+row.tag });
}, endrels);
};
action.loadResource = function(resId, callback) {
logger.debug('loading book ' + resId);
db.get('SELECT * FROM books WHERE id = '+ resId, function(err, row) {
callback(err, row);
});
};
callback(null, action);
break;
case 'list':
//TODO related
action.loadResources = function(onload, onend) {
var query = 'SELECT * FROM books ';
//TODO factorize
if (!this.perPage) this.perPage = 30;
//TODO sanitize
if (!this.page) this.page = 0;
query += ' LIMIT ? OFFSET ?';
db.each(query, this.perPage, this.page*this.perPage, function (err, row) {
onload(err, row);
}, function(err) {
//TODO err
if (err) logger.error(err);
onend();
});
};
callback(null, action);
break;
default:
callback(new Error('action not implemented'));
}
}, enumerable: true, configurable: true, writable: true
},
targetCollection : {
value: function(pathname) {
var match = PATH_RE.exec(pathname);
logger.debug('pathname ' + pathname + ' => ' + match);
if (match.length > 2 && match[2]) {
// TODO check integer
this.bookId = match[2];
return false;
}
return true;
}, enumerable: true, configurable: true, writable: true
}
});
exports = module.exports = new Book();

View File

@ -29,7 +29,7 @@ Endpoint.prototype = {
action = new Action.ShowAction(); action = new Action.ShowAction();
} }
if (action) { if (action) {
this.bind(action, function(err) { this.bind(action, url.query, function(err) {
callback(err, action); callback(err, action);
}); });
} else { } else {
@ -48,7 +48,7 @@ Endpoint.prototype = {
/** /**
* Bind action to endpoint resource. * Bind action to endpoint resource.
*/ */
bind : function(action, callback) { bind : function(action, params, callback) {
// implemented // implemented
callback(null, action); callback(null, action);
} }

View File

@ -8,7 +8,7 @@ function Library() {
Library.prototype = Object.create(Endpoint.prototype, { Library.prototype = Object.create(Endpoint.prototype, {
bind: { bind: {
value: function(action, callback) { value: function(action, params, callback) {
if (action.name == 'show') { if (action.name == 'show') {
action.resId = 'library'; action.resId = 'library';
action.loadResource = function(resId, callback) { action.loadResource = function(resId, callback) {
@ -17,8 +17,8 @@ Library.prototype = Object.create(Endpoint.prototype, {
name: 'Bibliothèque Meutel' name: 'Bibliothèque Meutel'
}); });
}; };
action.getRelated = function(res){ action.getRelated = function(res, relcback){
return new Array( relcback(null, new Array(
// authors list // authors list
{ type: 'authors', path: '/author/' }, { type: 'authors', path: '/author/' },
// books list // books list
@ -29,7 +29,7 @@ Library.prototype = Object.create(Endpoint.prototype, {
{ type: 'series', path: '/series/' }, { type: 'series', path: '/series/' },
// user favorites // user favorites
{ type: 'favorites', path:'/favorites/'} { type: 'favorites', path:'/favorites/'}
); ));
}; };
} }
callback(null, action); callback(null, action);