Create a Blog Application with Ruby on Rails 7. Fourth Part: Performing Operations on the Post Resource

In this article, we will implement the ability for users to create, update, delete, and publish posts.

All Parts:

  1.  Create a Blog Application with Ruby on Rails 7. First Part: Create the User Resource 
  2.  Create a Blog Application with Ruby on Rails 7. Second Part: Create a Post Model and a Posts Controller
  3.  Create a Blog Application with Ruby on Rails 7. Third Part: Implement User Authentication
  4.  Create a Blog Application with Ruby on Rails 7. Fourth Part: Performing Operations on the Post Resource
  5.  Create a Blog Application with Ruby on Rails 7. Fifth Part: Implement Authorization

First, let's declare the strong parameters in the private method post_params in the Posts controller:

private
 
 def post_params
   params.require(:post).permit(:title, :content, :status, :user_id)
 end

Next, we'll add the new method to the controller:

def new
   @post = Post.new
end

 Also, we'll create the corresponding view, new.html.erb, in the app/views/posts/ folder.

We'll create a _form.html.erb partial as well because we want to use the same form in both the new and edit views. Let's create this file and then put this code inside:

<%= form_with(model: post) do |form| %>
  <% if post.errors.any? %>
    <div style="color: red">
      <h2><%= pluralize(post.errors.count, "error") %> prohibited this post from being saved:</h2>
      <ul>
        <% post.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>
  <div>
    <%= form.label :title, style: "display: block" %>
    <%= form.text_field :title %>
  </div>
  <div>
    <%= form.label :content, style: "display: block" %>
    <%= form.text_area :content %>
  </div>
  <div>
    <%= form.submit %>
  </div>
<% end %>

Now, let's render it in the new.html.erb view. Let's edit this view as follows:

<p style="color: green"><%= notice %></p>
<h1>New Post</h1>
<%= render "form", post: @post %>
<p>
 <%= link_to "All posts", root_path %>
</p>

Let's put a link to this action on the post index view at the bottom:

<p>
  <%= link_to 'Add New Post', new_post_path %>
</p>

Of course, to be able to create a post, we must define a create method. Here we'll set the post's user to the user in the session:

def create
  @post = Post.new(post_params)
  @post.user = current_user
  respond_to do |format|
    if @post.save
      format.html {redirect_to @post, notice: 'Post was successfully created.'}
    else
      format.html { render :new, status: :unprocessable_entity }
    end
  end
end

Next, we add an edit method to our Posts controller:

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

Then we create the edit.html.erb view in the app/views/posts/ directory and edit it like this:

<h1>Editing post</h1>
<%= render "form", post: @post %>
<p>
  <%= link_to "All posts", root_path %>
</p>

Let's put a link to the edit action in the show.html.erb file, right before the closing </footer> tag:

<p>
  <%= link_to 'Edit', edit_post_path(@post) %>
</p>

Of course, for this form to work, we must define an update method in the Posts controller:

def update
  @post = Post.find(params[:id])
  respond_to do |format|
    if @post.update(post_params)
      format.html { redirect_to post_url(@post), notice: "Post was successfully updated." }
    else
      format.html { render :edit, status: :unprocessable_entity }
    end
  end
end

Next, we will implement the ability to delete posts. Let's define a destroy action in the controller:

def destroy
  @post = Post.find(params[:id])
  @post.destroy
  redirect_to root_path
  flash[:notice] = 'Post was successfully deleted.'
end

And in the post show view, below the link for editing the post, let's add a delete button:

<%= button_to "Delete", @post, method: :delete %>

Finally, let's add a publish method to the controller:

def publish
  @post = Post.find(params[:id])
  @post.published!
  redirect_to post_path(@post)
  flash[:notice] = 'Post was successfully published.'
end

Then we define a route to the publish action. Let's open the config/routes.rb file and edit the post resource block like this:

resources :posts do
  member do
    get :publish
  end
end

Last thing we'll do is to add a publish button in the post show view below the delete button:

<% if @post.draft? %>
  <%= link_to 'Publish', publish_post_path(@post) %>
<% end %>

Post last updated on Dec 17, 2023