Jeremy Ong
Jeremy Ong

Reputation: 37

AJAX call returns a 500 error - Ruby on Rails

I have an ajax call from my view that triggers when i click on the upvote/downvote buttons (which should be a POST http request). However, AJAX is returning a internal 500 error (I presume that it is because there is no vote view file)

Controller file

class PostsController < ApplicationController


def vote
    PostsVote.create(
        user_id: session[:id],
        post_id: vote_params[:post_id].to_i,
        vote: vote_params[:vote].to_i)
    @post = Post.find(vote_params[:post_id])
    votes_total = @post.posts_votes.sum(:vote)
    {post_id: @post.id, votes: votes_total}.to_json
end

private

def vote_params
    params.permit(:post_id, :vote)
end
end

View file with AJAX

<div class="container">
<h1>Welcome to Hacker News Clone</h1>

<h3>All posts</h3>
<ul>
<% @posts.each_with_index do |post, index| %>
  <li id="post<%= post.id %>">
    <a href="/posts/<%= post.id %>"><%= post.post_desc %>
    </a>
    <br/>
    <span>
      <%= @post_votes[index] %> points
    </span>
      by <a href="/users/<%= post.user.id %>"><%= post.user.username %></a> | <%= post.comments.count %> comments
    <br/>
    <button <%= "disabled" if post.posts_votes.find_by(user_id: session[:id]) && post.posts_votes.find_by_user_id(session[:id]).vote == 1 %> class="upvote" data-post-id="<%= post.id %>" width="40px" height="40px">Upvote</button>
    <button <%= "disabled" if post.posts_votes.find_by(user_id: session[:id]) && post.posts_votes.find_by_user_id(session[:id]).vote == -1 %> class="downvote" data-post-id="<%= post.id %>" width="40px" height="40px">Downvote</button>


  </li>
  <br/>
<% end %>
</ul>
</div>

<script>
$(document).ready(function() {

 // Check if any post-vote combination for that user already exists and change upvote/downvote button to disabled


$(".upvote").on("click", function(event) {
event.preventDefault();
var postId = $(this).data("post-id");
var url = "/posts/" + postId + "/vote"
$.ajax({
    type: "POST",
    url: url,
    data: {"post_id": postId,
           "vote": 1},
    dataType: "json"
  }).done(function(response){
    debugger
    $("#post" + response["post_id"] + " span").text(response["votes"] + " points");
    $("#post" + response["post_id"] + " button" + ".upvote").attr("disabled", "disabled")
});
});

$(".downvote").on("click", function(event) {
event.preventDefault();
var postId = $(this).data("post-id");
var url = "/posts/" + postId + "/vote"
$.ajax({
    type: "POST",
    url: url,
    data: {"post_id": postId,
           "vote": -1},
    dataType: "json"
  }).done(function(response){
    $("#post" + response["post_id"] + " span").text(response["votes"] + " points");
    $("#post" + response["post_id"] + " button" + ".downvote").attr("disabled", "disabled")
});
});


});
</script>

Any help would be greatly appreciated.

Upvotes: 0

Views: 526

Answers (1)

Wally Altman
Wally Altman

Reputation: 3545

You are correct; you're getting the error because Rails is trying to render the vote view, which doesn't exist. Since you didn't call render or redirect_to in the vote action, Rails by default tries to render the template.

It looks like you just want to respond with JSON, which you can do like this:

def vote
  PostsVote.create(
      user_id: session[:id],
      post_id: vote_params[:post_id].to_i,
      vote: vote_params[:vote].to_i)

  @post = Post.find(vote_params[:post_id])
  votes_total = @post.posts_votes.sum(:vote)

  render json: {post_id: @post.id, votes: votes_total} # to_json is called automatically
end

I've made the assumption that this action is always called via Ajax and always wants to return JSON. If you are going to have multiple types of responses, you'll need a respond_to block. Here's an example with respond_to from the official guides.

Upvotes: 1

Related Questions