Loading comments/lib/comments.js +6 −69 Original line number Diff line number Diff line var Targets = require("./targets"); var Formatter = require("./formatter"); var Tags = require("./tags"); /** * Represents a Comments table. Loading @@ -17,6 +18,7 @@ function Comments(db, domain) { this.db = db; this.domain = domain; this.targets = new Targets(db, domain); this.tags = new Tags(db, domain); this.view = "full_visible_comments AS comments"; this.fields = ["*"]; } Loading Loading @@ -371,82 +373,17 @@ Comments.prototype = { }, /** * Adds tag to the comment. * * @param {Object} tag * @param {Number} tag.user_id The user who's tagging. * @param {Number} tag.comment_id The comment that's tagged. * @param {Number} tag.tagname The text for the tag. * @param {Function} callback * @param {Error} callback.err * @inheritdoc Tags#add */ addTag: function(tag, callback) { this.ensureTag(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } // replace `tagname` with `tag_id` in tag object delete tag.tagname; tag.tag_id = tag_id; this.db.insert("comment_tags", tag, callback); }.bind(this)); this.tags.add(tag, callback); }, /** * Removes tag from comment. * * @param {Object} tag * @param {Number} tag.comment_id The comment with the tag. * @param {Number} tag.tagname The text of the tag. * @param {Function} callback * @param {Error} callback.err * @inheritdoc Tags#remove */ removeTag: function(tag, callback) { this.getTagId(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } var sql = "DELETE FROM comment_tags WHERE comment_id = ? AND tag_id = ?"; this.db.query(sql, [tag.comment_id, tag_id], callback); }.bind(this)); }, // Returns ID of the given tagname, // creating a new entry to tags table when needed. ensureTag: function(tagname, callback) { this.db.insert("tags", {domain: this.domain, tagname: tagname}, function(err, tag_id) { if (err && err.code === "ER_DUP_ENTRY") { // tag already exists, retrieve it this.getTagId(tagname, callback); } else if (err) { callback(err); } else { callback(null, tag_id); } }.bind(this)); }, // Simple lookup of tag ID by name getTagId: function(tagname, callback) { var sql = "SELECT * FROM tags WHERE tagname = ? AND domain = ?"; this.db.queryOne(sql, [tagname, this.domain], function(err, existingTag) { if (err) { callback(err); } else if (!existingTag) { callback("Tag '"+tagname+"' not found."); } else { callback(null, existingTag.id); } }); this.tags.remove(tag, callback); }, /** Loading comments/lib/tags.js 0 → 100644 +97 −0 Original line number Diff line number Diff line /** * Implements adding and removing of tags from comments and hides the * logic of managing the tags and comment_tags tables. * * @constructor * Initializes Tags with a database connection and a target domain. * * @param {DbFacade} db Instance of DbFacade. * @param {String} domain The comments domain within which to work. */ function Tags(db, domain) { this.db = db; this.domain = domain; } Tags.prototype = { /** * Adds tag to the comment. * * @param {Object} tag * @param {Number} tag.user_id The user who's tagging. * @param {Number} tag.comment_id The comment that's tagged. * @param {Number} tag.tagname The text for the tag. * @param {Function} callback * @param {Error} callback.err */ add: function(tag, callback) { this.ensure(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } // replace `tagname` with `tag_id` in tag object delete tag.tagname; tag.tag_id = tag_id; this.db.insert("comment_tags", tag, callback); }.bind(this)); }, /** * Removes tag from comment. * * @param {Object} tag * @param {Number} tag.comment_id The comment with the tag. * @param {Number} tag.tagname The text of the tag. * @param {Function} callback * @param {Error} callback.err */ remove: function(tag, callback) { this.getId(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } var sql = "DELETE FROM comment_tags WHERE comment_id = ? AND tag_id = ?"; this.db.query(sql, [tag.comment_id, tag_id], callback); }.bind(this)); }, // Returns ID of the given tagname, // creating a new entry to tags table when needed. ensure: function(tagname, callback) { this.db.insert("tags", {domain: this.domain, tagname: tagname}, function(err, tag_id) { if (err && err.code === "ER_DUP_ENTRY") { // tag already exists, retrieve it this.getId(tagname, callback); } else if (err) { callback(err); } else { callback(null, tag_id); } }.bind(this)); }, // Simple lookup of tag ID by name getId: function(tagname, callback) { var sql = "SELECT * FROM tags WHERE tagname = ? AND domain = ?"; this.db.queryOne(sql, [tagname, this.domain], function(err, existingTag) { if (err) { callback(err); } else if (!existingTag) { callback("Tag '"+tagname+"' not found."); } else { callback(null, existingTag.id); } }); } }; module.exports = Tags; comments/spec/comments.spec.js +0 −43 Original line number Diff line number Diff line Loading @@ -435,47 +435,4 @@ describe("Comments", function() { }); }); }); it("#getById includes concatenated list of tags in the returned comment", function(done) { comments.getById(1, function(err, com) { expect(com.tags).toEqual("bug\tfeature"); done(); }); }); it("#addTag adds existing tag to a comment", function(done) { comments.addTag({tagname: 'feature', comment_id: 3, user_id: 1}, function(err, com) { comments.getById(3, function(err, com) { expect(com.tags).toEqual("feature"); done(); }); }); }); it("#addTag adds new non-existing tag to a comment", function(done) { comments.addTag({tagname: 'blah', comment_id: 4, user_id: 1}, function(err, com) { comments.getById(4, function(err, com) { expect(com.tags).toEqual("blah"); done(); }); }); }); it("#removeTag removes tag from comment", function(done) { comments.removeTag({tagname: 'feature', comment_id: 2}, function(err, com) { comments.getById(2, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); it("#removeTag does nothing when removing non-existing tag", function(done) { comments.removeTag({tagname: 'blablabla', comment_id: 5}, function(err, com) { comments.getById(5, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); }); comments/spec/tags.spec.js 0 → 100644 +64 −0 Original line number Diff line number Diff line describe("Tags", function() { var mysql = require("mysql"); var Tags = require("../lib/tags"); var Comments = require("../lib/comments"); var DbFacade = require('../lib/db_facade'); var config = require('../config'); var connection; var comments; beforeEach(function() { connection = mysql.createConnection(config.testDb); // Test Tags class through the Comments class, // which just forwards two methods of the Tags class. comments = new Comments(new DbFacade(connection), "ext-js-4"); }); afterEach(function() { connection.end(); }); it("each comment has concatenated list of tags", function(done) { comments.getById(1, function(err, com) { expect(com.tags).toEqual("bug\tfeature"); done(); }); }); it("#addTag adds existing tag to a comment", function(done) { comments.addTag({tagname: 'feature', comment_id: 3, user_id: 1}, function(err, com) { comments.getById(3, function(err, com) { expect(com.tags).toEqual("feature"); done(); }); }); }); it("#addTag adds new non-existing tag to a comment", function(done) { comments.addTag({tagname: 'blah', comment_id: 4, user_id: 1}, function(err, com) { comments.getById(4, function(err, com) { expect(com.tags).toEqual("blah"); done(); }); }); }); it("#removeTag removes tag from comment", function(done) { comments.removeTag({tagname: 'feature', comment_id: 2}, function(err, com) { comments.getById(2, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); it("#removeTag does nothing when removing non-existing tag", function(done) { comments.removeTag({tagname: 'blablabla', comment_id: 5}, function(err, com) { comments.getById(5, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); }); Loading
comments/lib/comments.js +6 −69 Original line number Diff line number Diff line var Targets = require("./targets"); var Formatter = require("./formatter"); var Tags = require("./tags"); /** * Represents a Comments table. Loading @@ -17,6 +18,7 @@ function Comments(db, domain) { this.db = db; this.domain = domain; this.targets = new Targets(db, domain); this.tags = new Tags(db, domain); this.view = "full_visible_comments AS comments"; this.fields = ["*"]; } Loading Loading @@ -371,82 +373,17 @@ Comments.prototype = { }, /** * Adds tag to the comment. * * @param {Object} tag * @param {Number} tag.user_id The user who's tagging. * @param {Number} tag.comment_id The comment that's tagged. * @param {Number} tag.tagname The text for the tag. * @param {Function} callback * @param {Error} callback.err * @inheritdoc Tags#add */ addTag: function(tag, callback) { this.ensureTag(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } // replace `tagname` with `tag_id` in tag object delete tag.tagname; tag.tag_id = tag_id; this.db.insert("comment_tags", tag, callback); }.bind(this)); this.tags.add(tag, callback); }, /** * Removes tag from comment. * * @param {Object} tag * @param {Number} tag.comment_id The comment with the tag. * @param {Number} tag.tagname The text of the tag. * @param {Function} callback * @param {Error} callback.err * @inheritdoc Tags#remove */ removeTag: function(tag, callback) { this.getTagId(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } var sql = "DELETE FROM comment_tags WHERE comment_id = ? AND tag_id = ?"; this.db.query(sql, [tag.comment_id, tag_id], callback); }.bind(this)); }, // Returns ID of the given tagname, // creating a new entry to tags table when needed. ensureTag: function(tagname, callback) { this.db.insert("tags", {domain: this.domain, tagname: tagname}, function(err, tag_id) { if (err && err.code === "ER_DUP_ENTRY") { // tag already exists, retrieve it this.getTagId(tagname, callback); } else if (err) { callback(err); } else { callback(null, tag_id); } }.bind(this)); }, // Simple lookup of tag ID by name getTagId: function(tagname, callback) { var sql = "SELECT * FROM tags WHERE tagname = ? AND domain = ?"; this.db.queryOne(sql, [tagname, this.domain], function(err, existingTag) { if (err) { callback(err); } else if (!existingTag) { callback("Tag '"+tagname+"' not found."); } else { callback(null, existingTag.id); } }); this.tags.remove(tag, callback); }, /** Loading
comments/lib/tags.js 0 → 100644 +97 −0 Original line number Diff line number Diff line /** * Implements adding and removing of tags from comments and hides the * logic of managing the tags and comment_tags tables. * * @constructor * Initializes Tags with a database connection and a target domain. * * @param {DbFacade} db Instance of DbFacade. * @param {String} domain The comments domain within which to work. */ function Tags(db, domain) { this.db = db; this.domain = domain; } Tags.prototype = { /** * Adds tag to the comment. * * @param {Object} tag * @param {Number} tag.user_id The user who's tagging. * @param {Number} tag.comment_id The comment that's tagged. * @param {Number} tag.tagname The text for the tag. * @param {Function} callback * @param {Error} callback.err */ add: function(tag, callback) { this.ensure(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } // replace `tagname` with `tag_id` in tag object delete tag.tagname; tag.tag_id = tag_id; this.db.insert("comment_tags", tag, callback); }.bind(this)); }, /** * Removes tag from comment. * * @param {Object} tag * @param {Number} tag.comment_id The comment with the tag. * @param {Number} tag.tagname The text of the tag. * @param {Function} callback * @param {Error} callback.err */ remove: function(tag, callback) { this.getId(tag.tagname, function(err, tag_id) { if (err) { callback(err); return; } var sql = "DELETE FROM comment_tags WHERE comment_id = ? AND tag_id = ?"; this.db.query(sql, [tag.comment_id, tag_id], callback); }.bind(this)); }, // Returns ID of the given tagname, // creating a new entry to tags table when needed. ensure: function(tagname, callback) { this.db.insert("tags", {domain: this.domain, tagname: tagname}, function(err, tag_id) { if (err && err.code === "ER_DUP_ENTRY") { // tag already exists, retrieve it this.getId(tagname, callback); } else if (err) { callback(err); } else { callback(null, tag_id); } }.bind(this)); }, // Simple lookup of tag ID by name getId: function(tagname, callback) { var sql = "SELECT * FROM tags WHERE tagname = ? AND domain = ?"; this.db.queryOne(sql, [tagname, this.domain], function(err, existingTag) { if (err) { callback(err); } else if (!existingTag) { callback("Tag '"+tagname+"' not found."); } else { callback(null, existingTag.id); } }); } }; module.exports = Tags;
comments/spec/comments.spec.js +0 −43 Original line number Diff line number Diff line Loading @@ -435,47 +435,4 @@ describe("Comments", function() { }); }); }); it("#getById includes concatenated list of tags in the returned comment", function(done) { comments.getById(1, function(err, com) { expect(com.tags).toEqual("bug\tfeature"); done(); }); }); it("#addTag adds existing tag to a comment", function(done) { comments.addTag({tagname: 'feature', comment_id: 3, user_id: 1}, function(err, com) { comments.getById(3, function(err, com) { expect(com.tags).toEqual("feature"); done(); }); }); }); it("#addTag adds new non-existing tag to a comment", function(done) { comments.addTag({tagname: 'blah', comment_id: 4, user_id: 1}, function(err, com) { comments.getById(4, function(err, com) { expect(com.tags).toEqual("blah"); done(); }); }); }); it("#removeTag removes tag from comment", function(done) { comments.removeTag({tagname: 'feature', comment_id: 2}, function(err, com) { comments.getById(2, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); it("#removeTag does nothing when removing non-existing tag", function(done) { comments.removeTag({tagname: 'blablabla', comment_id: 5}, function(err, com) { comments.getById(5, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); });
comments/spec/tags.spec.js 0 → 100644 +64 −0 Original line number Diff line number Diff line describe("Tags", function() { var mysql = require("mysql"); var Tags = require("../lib/tags"); var Comments = require("../lib/comments"); var DbFacade = require('../lib/db_facade'); var config = require('../config'); var connection; var comments; beforeEach(function() { connection = mysql.createConnection(config.testDb); // Test Tags class through the Comments class, // which just forwards two methods of the Tags class. comments = new Comments(new DbFacade(connection), "ext-js-4"); }); afterEach(function() { connection.end(); }); it("each comment has concatenated list of tags", function(done) { comments.getById(1, function(err, com) { expect(com.tags).toEqual("bug\tfeature"); done(); }); }); it("#addTag adds existing tag to a comment", function(done) { comments.addTag({tagname: 'feature', comment_id: 3, user_id: 1}, function(err, com) { comments.getById(3, function(err, com) { expect(com.tags).toEqual("feature"); done(); }); }); }); it("#addTag adds new non-existing tag to a comment", function(done) { comments.addTag({tagname: 'blah', comment_id: 4, user_id: 1}, function(err, com) { comments.getById(4, function(err, com) { expect(com.tags).toEqual("blah"); done(); }); }); }); it("#removeTag removes tag from comment", function(done) { comments.removeTag({tagname: 'feature', comment_id: 2}, function(err, com) { comments.getById(2, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); it("#removeTag does nothing when removing non-existing tag", function(done) { comments.removeTag({tagname: 'blablabla', comment_id: 5}, function(err, com) { comments.getById(5, function(err, com) { expect(com.tags).toEqual(""); done(); }); }); }); });