Reputation: 37
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
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