Loading comments/app.js +18 −1 Original line number Diff line number Diff line Loading @@ -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)) { Loading comments/comments.js +56 −0 Original line number Diff line number Diff line Loading @@ -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)); } }; Loading comments/comments.spec.js +32 −0 Original line number Diff line number Diff line Loading @@ -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(); }); }); }); comments/sql/test_data.sql +2 −2 Original line number Diff line number Diff line Loading @@ -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'; Loading comments/sql/update_votes.sql +15 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
comments/app.js +18 −1 Original line number Diff line number Diff line Loading @@ -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)) { Loading
comments/comments.js +56 −0 Original line number Diff line number Diff line Loading @@ -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)); } }; Loading
comments/comments.spec.js +32 −0 Original line number Diff line number Diff line Loading @@ -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(); }); }); });
comments/sql/test_data.sql +2 −2 Original line number Diff line number Diff line Loading @@ -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'; Loading
comments/sql/update_votes.sql +15 −0 Original line number Diff line number Diff line Loading @@ -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;