Akash Pinnaka
Akash Pinnaka

Reputation: 475

Clicking on the link is not triggering the action

I am beginner in ruby on rails. I am building a movie review app for practising ruby on rails. In that application I am adding voting feature for movies (upvote and downvote).

Movies#index

<%= link_to "Add movie", new_movie_path %>
  <% @movies.each do |movie| %>
    <%= image_tag movie.thumbnail.url(:medium) %>
    <%= link_to movie.title, movie_path(movie) %>
    <%= link_to "upvote", {controller: "votes", action: "upvote"} %>
    <%= link_to "downvote",{controller:"votes", action: "downvote"} %>
  <% end %>

Votes controller

class MoviesController < ApplicationController
  def upvote
    Movie.find(params[:id]).vote.upvote += 1
    redirect_to movies_path
  end

  def downvote
    Movie.find(params[:id]).vote.downvote += 1
    redirect_to movies_path
  end
end

routes.rb

Rails.application.routes.draw do    
  resources :movies    
  resources :votes
  root 'movies#index'  
end

When I click on the links upvote and downvote(movies#index), the upvote and downvote actions are not triggering. It is throwing error

No route matches {:action=>"upvote", :controller=>"votes"}

Upvotes: 1

Views: 87

Answers (2)

Doru P&#238;rvu
Doru P&#238;rvu

Reputation: 340

Your "votes_controller.rb" has defined MoviesController. Is it a typo ?

Also you need to define your custom resource routes. See http://guides.rubyonrails.org/routing.html for more about routing in rails

I would also suggest you create a Vote model use

resources :votes

Vote model will have: id: int type: string movie_id: int

And in view:

link_to 'Upvote', vote_path(movie_id: movie.id, type: 'up'), method: post
link_to 'Downvote', vote_path(movie_id: 42, type: 'down'), method: post

I am maybe mistaking the auto-generated path methods; to see all available routes from your app, open a terminal, navigate to your rails root folder and run: rake routes

All is explained in the link above

Upvotes: 2

guitarman
guitarman

Reputation: 3310

I suggest to use a resource definition for movies only and in addition two routes for upvote and downvote a movie:

Rails.application.routes.draw do
  resources :votes do
    member do
      get 'upvote'
      get 'downvote'
    end
  end
end

If you run rake routes now you get a nice list of routes to manage your movies and in addition the two more routes. All paths are processed in different actions of one controller.

~/dev/rubyonrails/test_app$rake routes
        Prefix Verb   URI Pattern                    Controller#Action 
  upvote_movie GET    /movies/:id/upvote(.:format)   movies#upvote
downvote_movie GET    /movies/:id/downvote(.:format) movies#downvote
        movies GET    /movies(.:format)              movies#index
               POST   /movies(.:format)              movies#create
     new_movie GET    /movies/new(.:format)          movies#new
    edit_movie GET    /movies/:id/edit(.:format)     movies#edit
         movie GET    /movies/:id(.:format)          movies#show
               PATCH  /movies/:id(.:format)          movies#update
               PUT    /movies/:id(.:format)          movies#update
               DELETE /movies/:id(.:format)          movies#destroy
~/dev/rubyonrails/test_app$

Now you can use the route helpers (see Prefix in the list):

<%= link_to "upvote", upvote_movie_path(movie) %>
<%= link_to "down vote", downvote_movie_path(movie) %>

The movie object brings the :id attribute in the route paths, so you know which movie should be up or down voted.

Note the words of the router helper names. These sound like that what you want to do: upvote movie or downvote movie

Upvotes: 1

Related Questions