Commit f3e0be83 authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Refactor tags related methods to Tags class.

parent b457c045
Loading
Loading
Loading
Loading
+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.
@@ -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 = ["*"];
}
@@ -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);
    },

    /**

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;
+0 −43
Original line number Diff line number Diff line
@@ -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();
            });
        });
    });
});
+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();
            });
        });
    });
});