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