goals {
goal "Add a button people can click to cast a vote."
}
steps {
step "Add a new route for voting" do
message "Open `config/routes.rb` and find the section that looks like this:"
source_code :ruby, <<-RUBY
resources :topics
RUBY
message "Replace that line so it looks like this:"
source_code :ruby, <<-RUBY
resources :topics do
member do
post 'upvote'
end
end
RUBY
message <<-MARKDOWN
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.
MARKDOWN
end
step "Add a new controller action for voting" do
message "Edit `app/controllers/topics_controller.rb` and add this method at the beginning the controller, after the `before_action` line"
source_code :ruby, <<-RUBY
def upvote
@topic = Topic.find(params[:id])
@topic.votes.create
redirect_to topics_path, notice: "Topic was successfully created."
end
RUBY
message <<-MARKDOWN
* `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).
MARKDOWN
end
step "Add the button to the view" do
message "Edit `app/views/topics/_topic.html.erb`: replace the closing `</div>` so that end of the file looks like this:"
source_code :erb, <<-HTML
<p>
<strong>Votes:</strong>
<%= pluralize(topic.votes.count, "vote") %>
<%= button_to '+1', upvote_topic_path(topic), method: :post %>
</p>
</div>
HTML
message <<-MARKDOWN
* `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.
MARKDOWN
end
step "Confirm your changes in the browser" do
message "Go back to your app and play."
end
}
commitnow do
message "find a good commit message and commit your changes"
end
next_step "make_the_topic_title_a_link"