Commit 3621df8d authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Implement voting.

Added triggers to database to recalculate the comments.vote column when
votes table is updated.

Plus minor fix to test data.
parent 73f663ef
Loading
Loading
Loading
Loading
+18 −1
Original line number Diff line number Diff line
@@ -148,7 +148,24 @@ app.get('/auth/:sdk/:version/comments/:commentId', services.comments, function(r
app.post('/auth/:sdk/:version/comments/:commentId', services.requireLogin, services.comments, services.users, function(req, res) {
    req.comments.getById(req.params.commentId, function(err, comment) {
        if (req.body.vote) {
            // TODO: voting...
            if (req.session.user.id === comment.user_id) {
                res.json({success: false, reason: 'You cannot vote on your own content'});
                return;
            }

            var vote = {
                user_id: req.session.user.id,
                comment_id: comment.id,
                value: req.body.vote === "up" ? 1 : -1
            };

            req.comments.vote(vote, function(err, voteDir, total) {
                res.json({
                    success: true,
                    direction: voteDir === 1 ? "up" : (voteDir === -1 ? "down" : null),
                    total: total
                });
            });
        }
        else {
            if (!req.users.canModify(req.session.user, comment)) {
+56 −0
Original line number Diff line number Diff line
@@ -228,6 +228,62 @@ Comments.prototype = {
                created_at: new Date()
            }, callback);
        }.bind(this));
    },

    /**
     * Votes a comment up or down.
     *
     * @param {Object} vote
     * @param {Number} vote.user_id The user who's voting
     * @param {Number} vote.comment_id The comment he's voting on
     * @param {Number} vote.value The value of the vote (1 or -1)
     * @param {Function} callback
     * @param {Error} callback.err
     * @param {Number} callback.resultingVote The vote that was actually casted (-1, 1 or 0)
     * @param {Number} callback.resultingTotal The final voting score for the comment.
     */
    vote: function(vote, callback) {
        this.castVote(vote, function(err, voteDir) {
            if (err) {
                callback(err);
                return;
            }

            var sql = "SELECT vote FROM comments WHERE id = ?";
            this.db.queryOne(sql, [vote.comment_id], function(err, comment) {
                callback(err, voteDir, comment && comment.vote);
            });
        }.bind(this));
    },

    castVote: function(vote, callback) {
        vote.created_at = new Date();
        this.db.insert("votes", vote, function(err, vote_id) {
            if (err) {
                // vote already exists, retrieve it
                var sql = "SELECT * FROM votes WHERE user_id = ? AND comment_id = ?";
                this.db.queryOne(sql, [vote.user_id, vote.comment_id], function(err, oldVote) {
                    if (err) {
                        callback(err);
                    }
                    else if (oldVote.value !== vote.value) {
                        // We're either upvoting a downvote or downvoting an upvote.
                        // In both cases the result is zero, so we remove the vote completely.
                        var sql = "DELETE FROM votes WHERE user_id = ? AND comment_id = ?";
                        this.db.query(sql, [vote.user_id, vote.comment_id], function(err) {
                            callback(err, 0);
                        });
                    }
                    else {
                        // can't upvote or downvote twice, so ignore and do nothing
                        callback(null, 0);
                    }
                }.bind(this));
            }
            else {
                callback(null, vote.value);
            }
        }.bind(this));
    }
};

+32 −0
Original line number Diff line number Diff line
@@ -222,4 +222,36 @@ describe("Comments", function() {
        });
    });

    it("#vote(value:1) votes a comment up", function(done) {
        comments.vote({value: 1, comment_id: 7, user_id: 3}, function(err, voteDir, total) {
            expect(voteDir).toEqual(1);
            expect(total).toEqual(3);
            done();
        });
    });

    it("#vote(value:-1) votes a comment down", function(done) {
        comments.vote({value: -1, comment_id: 15, user_id: 3}, function(err, voteDir, total) {
            expect(voteDir).toEqual(-1);
            expect(total).toEqual(-2);
            done();
        });
    });

    it("#vote(value:-1) on already upvoted comment eliminates the vote", function(done) {
        comments.vote({value: -1, comment_id: 19, user_id: 1}, function(err, voteDir, total) {
            expect(voteDir).toEqual(0);
            expect(total).toEqual(0);
            done();
        });
    });

    it("#vote(value:1) on already downvoted comment eliminates the vote", function(done) {
        comments.vote({value: 1, comment_id: 6, user_id: 3}, function(err, voteDir, total) {
            expect(voteDir).toEqual(0);
            expect(total).toEqual(-2);
            done();
        });
    });

});
+2 −2
Original line number Diff line number Diff line
@@ -129,8 +129,8 @@ INSERT INTO votes SET `user_id` = 2, `comment_id` = 15, `value` = -1, `created_a
INSERT INTO votes SET `user_id` = 1, `comment_id` = 19, `value` = 1, `created_at` = '2011-01-01 00:00:00';

-- +2 votes to mary in guide:testing
INSERT INTO votes SET `user_id` = 4, `comment_id` = 19, `value` = 1, `created_at` = '2011-01-01 00:00:00';
INSERT INTO votes SET `user_id` = 2, `comment_id` = 19, `value` = 1, `created_at` = '2011-01-01 00:00:00';
INSERT INTO votes SET `user_id` = 4, `comment_id` = 24, `value` = 1, `created_at` = '2011-01-01 00:00:00';
INSERT INTO votes SET `user_id` = 2, `comment_id` = 24, `value` = 1, `created_at` = '2011-01-01 00:00:00';

-- 3-1 votes to jack in video:17666102
INSERT INTO votes SET `user_id` = 2, `comment_id` = 25, `value` = 1, `created_at` = '2011-01-01 00:00:00';
+15 −0
Original line number Diff line number Diff line
@@ -2,3 +2,18 @@

UPDATE comments
SET vote = (SELECT SUM(value) FROM votes WHERE votes.comment_id = comments.id);


-- set up a trigger to recalculate the votes column automatically

CREATE TRIGGER on_vote_added AFTER INSERT ON votes
FOR EACH ROW
    UPDATE comments
    SET vote = (SELECT SUM(value) FROM votes WHERE votes.comment_id = comments.id)
    WHERE id = NEW.comment_id;

CREATE TRIGGER on_vote_deleted AFTER DELETE ON votes
FOR EACH ROW
    UPDATE comments
    SET vote = (SELECT SUM(value) FROM votes WHERE votes.comment_id = comments.id)
    WHERE id = OLD.comment_id;