Creating Simple Blogging Platform - Editing Posts
By: Lukasz Muzyka, On:
This tutorial assumes you have already completed:
- Install Ruby on Rails
- Create Ruby on Rails application
- Create Static Pages - without this deploy will not work
- Install Git
- Create Remote Git Repository - optional but recommended
- Deploy application to Heroku
- Manage users with Devise
- How to add Twitter Bootstrap to Ruby on Rails application - Advised
- Creating Simple Blogging Platform - Creating Model
- Creating Simple Blogging Platform - Routes
- Creating Simple Blogging Platform - Displaying Posts
- Creating Simple Blogging Platform - Building Posts
Once we've created posts, it's time to allow our users to edit their posts.
Step 1: Edit Action
We'll start by defining new action in the controller:
app/controllers/posts_controller.rb
def edit
@post = Post.find(params[:id])
end
private
We're using params[:id]
the same way as when we were looking for the post to show up. This time, however, we want to make sure the owner of the post is the only one allow to have access and make changes to his/her post.
app/controllers/posts_controller.rb
def edit
@post = Post.find(params[:id])
redirect_to posts_path unless @post.user == current_user
end
Step 2: Create New html File
Now, we can create an HTML page that matches th action's name. Inside posts
folder, create a new file and call it "edit.html.erb". Add the code below:
app/views/posts/edit.html.erb
<%= form_for @post do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :title, class: 'control-label' %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group>
<%= f.label :body, class: 'control-label' %>
<%= f.text_area :body, class: 'form-control', rows: 6 %>
</div>
<%= f.submit 'Save', class: 'btn btn-primary %>
<% end %>
You have probably noticed, that this form looks identical to the new.html.erb
. In order to keep our code DRY (don't repeat yourself). We will extract this form into a partial which we can later render on both new and edit pages. In app/views/posts/
create new file and call it "_form.html.erb".
app/views/posts/_form.html.erb
<%= form_for post do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="form-group">
<%= f.label :title, class: 'control-label' %>
<%= f.text_field :title, class: 'form-control' %>
</div>
<div class="form-group>
<%= f.label :body, class: 'control-label' %>
<%= f.text_area :body, class: 'form-control', rows: 6 %>
</div>
<%= f.submit 'Save', class: 'btn btn-primary' %>
<% end %>
Make sure you change "@post" to "post"
Step 3: Replace Old Form in New Files
Now, we can replace the old form in new and edit with single line pointing to the partial:
app/views/posts/new.html.erb
<h1>New Post</h1>
<%= render 'form', post: @post %>
app/views/posts/edit.html.erb
<h1>Edit post</h1>
<p><%= link_to 'back', post_path(@post) %></p>
<%= render 'form', post: @post %>
Also, let's add link to edit page in "show" template. In between the tag h1, add from line 3 to line 6:
app/views/posts/show.html.erb
<h1>
<%= @post.title %>
<% if @post.user == current_user %>
<small><%= link_to 'edit', edit_post_path(@post) %></small>
<% end %>
</h1>
<p><small><strong>By: </strong><%= @post.user.email %></small></p>
<p><%= @post.body %></p>
We can add this code using more concise short hand version with content_tag. Although, I believe it might be a little confusing at the beginning.
app/views/posts/show.html.erb
<h1><%= @post.title %> <%= content_tag(:small, link_to('edit', edit_post_path(@post))) if @post.user == current_user %></h1>
<p><small><strong>By: </strong><%= @post.user.email %></small></p>
<p><%= @post.body %></p>
Step 4: Update action
Our editing feature almost done. However, it's unable to save in the data base all the changes we submit in edit form. To maintain those changes we will use "Update" action.
In projects controller:
/app/controllers/posts_controller.rb
class PostsController < ApplicationController
# existing code
def update
@post = Post.find(params[:id])
if @post.user == current_user
if @post.update_attributes(allowed_params)
flash[:success] = "Updated post"
redirect_to @post
else
render 'edit'
end
else
redirect_to posts_path
flash[:notice] = "You can't to this"
end
end
private
def allowed_params
params.require(:post).permit(:title, :body)
end
end
As you can see the code is similar to the "create" action, however this time, we need to check if the owner of the post is the current_user. Also, instead of building new post we uptate_attributes
.
Notice how both create and update actions don't have their own HTML templates. We simply redirect the user after we perform the work.
Go ahead and take it for a spin.
On: nate wrote:
There is a missing '
app/views/posts/edit.html.erb
<%= f.submit 'Save', class: 'btn btn-primary %>
On: nate wrote:
app/views/posts/_form.html.erb is missing "
Comment
You can login to comment