2
\$\begingroup\$

In the app I'm creating, when a user upvotes a post, the post should be upvoted, as well as the user that wrote the post. But this updates two MongoDB documents. This presents a number of issues. I'll first provide an overview of the code and then list the issues.

A user clicks on an upvote button, which calls the vm.upvote function below. This in turn calls a function in the postService.js also below, which is where the AJAX request is made to update the database.

The code in the success block reloads the post data (which is already done initially) so that the information (number of upvotes) on the page updates immediately. If I don't add this, it won't do so. Is there a better way to accomplish this?

postController.js

vm.upvote = function() {

  Post.upvotePost(vm.post._id)
      .success(function(data) {

        Post.get($routeParams.post_id)
          .success(function(data) {
            vm.post = data;
            Post.getUserId(vm.post.authorId)
              .success(function(data) {
                vm.post.userData = data;
              });

          });
      });
  };

Even though this is a post factory, this function should probably be in a user factory since it is retrieving data relating to the user. Is it acceptable to have this here?

postService.js

postFactory.getUserId = function(id) {
    return $http.get('/api/users/' + id);
};

postFactory.upvotePost = function(id) {
    return $http.put('/api/posts/' + id + '/upvote')
}

The main issue here is that I am again nesting database calls. I first add an upvote to the post Model and depending on whether the user has already upvoted it or not (clicking the button twice, unupvotes), the user model is called and a counter is either incremented or decremented accordingly. This isn't modular. Again, is there a better way?

api.js

apiRouter.route('/posts/:post_id/upvote')
  .put(function(req, res) {
    Post.findById(req.params.post_id, function(err, post) {
      var index = post.likes.indexOf(req.decoded._id);
      if (index === -1) {
        post.likes.push(req.decoded._id);

        User.findById(post.authorId, function(err, user) {
          user.upvotes += 1;
          user.save(function(err) {
            // I can't place anything here since it can only return one error message.
          });
        });

      } else if (post.likes.length === 1 && post.likes[0] === req.decoded._id) {
          post.likes = [];

          User.findById(post.authorId, function(err, user) {
            user.upvotes -= 1;
            user.save(function(err) {
              // I can't place anything here.
            });
          });

      } else {
          var left = post.likes.slice(0, index);
          var right = post.likes.slice(index+1, post.likes.length);
          post.likes = left + right;

          User.findById(post.authorId, function(err, user) {
            user.upvotes -= 1;
            user.save(function(err) {
            });
          });

      };

      post.save(function(err) {
        if (err) res.send(err);
      });

      res.json({ "Post upvoted!" });

    });
});
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.