Other Pages

Expand All

Allow People To Vote

Goals

    Now we're going to add a button people can click to cast a vote.

Steps

Step 1: Add a new controller action for voting

Edit app/controllers/topics_controller.rb to add the new method. You can put it anywhere in the file as long as it appears before the word private.

def upvote
  @topic = Topic.find(params[:id])
  @topic.votes.create
  redirect_to(topics_path)
end
  • @topic = Topic.find(params[:id]) finds the topic in the database with that id and stores it in the variable @topic.
  • @topic.votes.create creates a new vote for the current topic and saves it in the database.
  • redirect_to(topics_path) tells the browser to go back to topics_path (the topics list).

Step 2: Add a new route for voting

Open config/routes.rb and find the section that looks like this:

resources :topics

Replace that line so it looks like this:

resources :topics do
  member do
    post 'upvote'
  end
end

Verify that route route was added successfully by checking the output of rake routes or http://localhost:3000/rails/info. You should see a line that looks like this:

      Prefix Verb   URI Pattern                  Controller#Action
upvote_topic POST   /topics/:id/upvote(.:format) topics#upvote

Step 3: Add the button to the view

Edit app/views/topics/index.html.erb so that the bottom loop looks like this:

<% @topics.each do |topic| %>
  <tr>
    <td><%= topic.title %></td>
    <td><%= topic.description %></td>
    <td><%= pluralize(topic.votes.count, "vote") %></td>
    <td><%= button_to '+1', upvote_topic_path(topic), method: :post %></td>
    <td><%= link_to 'Show', topic %></td>
    <td><%= link_to 'Edit', edit_topic_path(topic) %></td>
    <td><%= link_to 'Destroy', topic, method: :delete, data: { confirm: 'Are you sure?' } %></td>
  </tr>
<% end %>
  • pluralize(topic.votes.count, "vote") displays the number of votes the topic has, plus the word 'vote' or 'votes' accordingly.
  • button_to '+1' creates an html button with the text '+1'.
  • topic_upvote_path(topic) creates the appropriate URL for the action we want to invoke. In this case, we want to upvote the current topic.
    • topic_upvote_path(topic) would return /topics/42/upvote (if topic.id was 42)
  • method: :post ensures we do the create action of CRUD, not the read action.

Step 4: Confirm your changes in the browser

Go back to http://localhost:3000/topics and play.

Revel in the fact that you didn't have to restart the server to see these changes. Awesome, no?

Pair teach again with sticky notes and paper

It's talking time again! Describe what you've just done, and the steps you took, with a partner.

If there are things you're unsure about, write them down too, then ask a teacher to explain.

Deploying

Before the next step, you could try deploying your app to Heroku!

Back to Hooking Up Votes And Topics

If you find something that could be improved, please make a pull request or drop us a note via GitHub Issues (no technical knowledge required).

Source: https://github.com/RailsBridge-CapeTown