Creating Simple Blogging Platform - Deleting Posts

By:, On:

This tutorial assumes you have already completed:

  1. Install Ruby on Rails
  2. Create Ruby on Rails application
  3. Create Static Pages - without this deploy will not work
  4. Install Git
  5. Create Remote Git Repository - optional but recommended
  6. Deploy application to Heroku
  7. Manage users with Devise
  8. How to add Twitter Bootstrap to Ruby on Rails application - Advised
  9. Creating Simple Blogging Platform - Creating Model
  10. Creating Simple Blogging Platform - Routes
  11. Creating Simple Blogging Platform - Displaying Posts
  12. Creating Simple Blogging Platform - Building Posts
  13. Creating Simple Blogging Platform - Editing Posts

One final thing we want to allow users to do is to delete posts they don't want. Fortunately, given all the foundation work we have already done, this will be an easy task.

Step 1: Create Controller Action

Same as before, we will start by creating controller action:

/app/controllers/posts_controller.rb


class PostsController < ApplicationController

    # existing code

    def destroy
        @post = Post.find(params[:id])
        if @post.user == current_user
            @post.destroy
            redirect_to posts_path
        else
            redirect_to root_path
            flash[:danger] = "You can't do this"
        end
    end

    private
        def allowed_params
            params.require(:post).permit(:title, :body)
        end
end

Just as we did before, we will have to find our post in the database. We will use :id from the URL in order to perform the search. Next, we will check if post belongs to the user who wants to delete it. If not, we will redirect him to the home page and flash an error, otherwise, we will delete the record and take the user back to all posts' list.

Step 2: Add Link

Now, we need to create link that can trigger delete action. User would probably expect "delete" link to be in the edit page:

app/views/posts/edit.html.erb


    <h1>Edit post</h1>
    <p><%= link_to 'back', post_path(@post) %></p>
    <%= render 'form', post: @post %>
    <br />
    <p><%= link_to 'delete post', @post, method: :delete, data: {confirm: "Are you sure you want to delete this permanently?"} %></p>

Step 3: Some refactoring

When we look at our controller we can easily notice, that there is some repeatable code in it. Let's refactor that, without going too crazy this time.

First, let's extract finding post with params[:id] and run it as before filter for those actions that use it:

/app/controllers/posts_controller.rb


class PostsController < ApplicationController
  before_filter :authenticate_user!, except: [:index, :show]
  before_filter :find_post, only: [:show, :edit, :update, :destroy]

  def index
    @posts = Post.all
  end

  def show
    # @post = Post.find(params[:id])## NOT NEEDED ANYMORE MOVED TO BEFORE FILTER
  end

  def new
    @post = Post.new
  end

  def create

    @user = current_user
    @post = @user.posts.build(allowed_params)

    if @post.save
      flash[:success] = "Created new post"
      redirect_to @post
    else
      render 'new'
    end
  end

  def edit
    # @post = Post.find(params[:id])## NOT NEEDED ANYMORE MOVED TO BEFORE FILTER
    redirect_to posts_path unless @post.user == current_user
  end

  def update
    # @post = Post.find(params[:id])## NOT NEEDED ANYMORE MOVED TO BEFORE FILTER
    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 do this"
    end
  end

  def destroy
    # @post = Post.find(params[:id])## NOT NEEDED ANYMORE MOVED TO BEFORE FILTER
    if @post.user == current_user
      @post.destroy
      redirect_to posts_path
      flash[:success] = "deleted post"
    else
      redirect_to root_path
      flash[:danger] = "You can't do this"
    end
  end

  private
    def allowed_params
      params.require(:post).permit(:title, :body)
    end

    def find_post
        @post = Post.find(params[:id])
    end

end

We could do a little more, but for now it's enough. Final version of the controller looks like this:

/app/controllers/posts_controller.rb


class PostsController < ApplicationController
  before_filter :authenticate_user!, except: [:index, :show]
  before_filter :find_post, only: [:show, :edit, :update, :destroy]

  def index
    @posts = Post.all
  end

  def show
  end

  def new
    @post = Post.new
  end

  def create
    @user = current_user
    @post = @user.posts.build(allowed_params)

    if @post.save
      flash[:success] = "Created new post"
      redirect_to @post
    else
      render 'new'
    end
  end

  def edit
    redirect_to posts_path unless @post.user == current_user
  end

  def update
    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 do this"
    end
  end

  def destroy
    if @post.user == current_user
      @post.destroy
      redirect_to posts_path
      flash[:success] = "deleted post"
    else
      redirect_to root_path
      flash[:danger] = "You can't do this"
    end
  end

  private
    def allowed_params
      params.require(:post).permit(:title, :body)
    end

    def find_post
        @post = Post.find(params[:id])
    end
end

If you login you will be able to mark this tutorial as finished to track your progress



Comment

You can login to comment