Now, post editing works, but if you were to look at the beginning of our show_post
and edit_post
actions, you'd notice that the logic to look up a post in the database is the same in each. So before we move on, let's take a moment to refactor this logic into its own method to make it more reusable.
### app/controllers/application_controller.rb ###
class ApplicationController < ActionController::Base
# ...
def show_post
post = find_post_by_id(params['id'])
render 'application/show_post', locals: { post: post }
end
# ...
def edit_post
post = find_post_by_id(params['id'])
render 'application/edit_post', locals: { post: post }
end
# ...
def find_post_by_id(id)
connection.execute("SELECT * FROM posts WHERE posts.id = ? LIMIT 1", id).first
end
end
Here we simply move the line we've been using to look up individual posts into its own method, named find_post_by_id
. Then we use it in both show_post
and edit_post
like so:
post = find_post_by_id(params['id'])
Again, refactoring our logic into one place like this makes it:
NOTE: Make sure not to delete the three original posts, or you may run into errors later in the book.
At this point we can view posts, create them, edit them, but we can't yet delete them, so that'll be our next step.
To do this, we'll just need something a user can click to send a request that deletes a post. But since deleting a post is destructive, we won't want to use a GET
request for this. Instead, we'll use a POST
request, and to perform this POST
, we'll need to create a <form>
to submit.
This <form>
will be incredibly simple though, because it will have no <input>
s, except for a submit button. All it needs to do is POST
to the path for destroying the post.
Here's what it looks like:
<!-- app/views/application/list_posts.html.erb -->
<html>
<body>
<div class="posts">
<% posts.each do |post| %>
<div class="post">
<h2 class="title"> <!-- ... --> </h2>
<small class="meta">
<!-- ... -->
</small>
<!-- ... -->
<form method="post" action="/delete_post/<%= post['id'] %>" style='display: inline'>
<input type="submit" value="Delete" />
</form>
</div>
<hr />
<% end %>
</div>
<!-- ... -->
</body>
</html>
Then the route our new <form>
points to:
### config/routes.rb ###
Rails.application.routes.draw do
# ...
post '/delete_post/:id' => 'application#delete_post'
end
And the action that routes to:
### app/controllers/application_controller.rb ###
class ApplicationController < ActionController::Base
# ...
def delete_post
connection.execute("DELETE FROM posts WHERE posts.id = ?", params['id'])
redirect_to '/list_posts'
end
end
We start off in application/list_posts
by giving each of our posts a <form>
:
<form method="post" action="/delete_post/<%= post['id'] %>" style='display: inline'>
<input type="submit" value="Delete" />
</form>
This will result in a Delete
button for each post.
The <form>
action
has the format /delete_post/:id
, so we route those requests to application#delete_post
.
Inside application#delete_post
, we see the familiar pattern we noticed in create_post
and update_post
(the other actions that receive POST
requests):
Now is a good time to go and try out some of the functionalities we've built into our app. We should now be able to create, edit, and delete posts.