ruby-on-railsacts-as-votable

Why isn't my acts as votable working?


When I click upvote I get an error enter image description here

Heres my routes.rb

  Rails.application.routes.draw do
  #root 'pages#index'
  resources :posts

  devise_for :users
  # Define root URL
  root 'pages#index'

  # Define roots for pages
  get '/home' => 'pages#home'

  get '/user/:id' => 'pages#profile'

  get '/explore' => 'pages#explore'

  resources :posts do
    member do
      put "like", to: "posts#upvote"  # maybe change it to POSTS??
      put "dislike", to: "posts#downvote" # maybe change it to POSTS??
    end
  end

And my posts_controller.rb

class PostsController < ApplicationController
  #resources posts
  def new
    @post = current_user.posts.build
  end

  def index
    @post = Post.all
  end

  def show
    @post = Post.find(params[:id])
  end

  def create
    @user = User.find(session[:user_id])
    @post = current_user.posts.build(permit_post)
    if @post.save
      flash[:success] = "Uploaded"
      redirect_to '/'
    else 
      flash[:error] = @posts_errors_full_messages
    end  
  end  

  def upvote
      current_user = User.find_by_id(session[:user_id])
      @post = Post.find(params[:id])
      current_user.upvotes @post
      redirect_to :back
  end

  def downvote
  @post = Post.find(params[:id])
  @post.downvote_by current_user
  redirect_to :back
  end

  private 
    def permit_post
    params.require(:post).permit(:image, :title);
    end
end

And I have in my index

<%= link_to like_post_path(@post), method: :put, class: 'upvote' do %>

In the URL its showing myurl.com/posts/%23/like I think this means its not getting the id, how can I fix it? This is literally exhausting me, thanks in advance

EDIT: I replaced @post with x since I was using a loop, that fixed the url but still getting the same error which is Couldn't find Post without an ID.


Solution

  • If you pass the id of the post, since like is a member (child) of a post, the link should look like /posts/41/like

    Next, you should remove the .exists? part from the controller. That kind of thing only belongs in the model.

    Update

    Your controller should look more like:

    def upvote
      # current_user = User.find_by_id(session[:user_id]) -- since you use devise, you don't need this
      @post = Post.find(params[:id])
      current_user.upvotes @post
      redirect_to :back
    end
    

    And your view link

    <%= link_to like_post_path(@post), method: :put, class: 'upvote' do %>
    

    Are you following a tutorial? find_by_id is not suggested in Rails 4. Did you create your own authentication or are you using a gem?

    update 2

    It's not rails convention to use a singular name when referring to a collection (thus my assumption about your earlier link with @post). So if you're trying to vote on your post index page, then your posts controller should be

    def index
      @posts = Post.all
    end
    

    And your view loop would be

    <%= @posts.each do |post|
     <!-- Other view code here for what you want to display >
     <%= link_to like_post_path(post), method: :put, class: 'upvote' do %>  
    <% end %>