Other Pages

Allow People To Vote

Goals

  • Add a button people can click to cast a vote.

Steps

Step 1: 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 upvote route was added successfully by checking the output of rails routes -c topic. You should see a new line that looks like this:

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

We are using POST instead of the more common GET, because we want to change something on the server.

Step 2: Add a new controller action for voting

Edit app/controllers/topics_controller.rb and add this method at the beginning the controller, after the before_action line

def upvote
  @topic = Topic.find(params[:id])
  @topic.votes.create
  redirect_to topics_path, notice: "Topic was successfully created."
end
  • params[:id] reads a parameter called id from the URL or from data sent via a form
  • @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 this topic and saves it in the database.
  • redirect_to(topics_path) tells the browser to go back to topics_path (the topics list).

Step 3: Add the button to the view

Edit app/views/topics/_topic.html.erb: replace the closing </div> so that end of the file looks like this:

  <p>
    <strong>Votes:</strong>
    <%= pluralize(topic.votes.count, "vote") %>
    <%= button_to '+1', upvote_topic_path(topic), method: :post %>
  </p>

</div>
  • 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" and the following properties:
    • upvote_topic_path(topic) creates the appropriate URL for the action we want to invoke. For the topic with id 42 this would be /topics/42/upvote
    • method: :post to fit with the route we specified before.

Step 4: Confirm your changes in the browser

Go back to your app and play.

Now would be a good time to commit to git

find a good commit message and commit your changes

Next Step: