In this article, we will implement the ability for users to create, update, delete, and publish posts.
All Parts:
- Create a Blog Application with Ruby on Rails 7. First Part: Create the User Resource
- Create a Blog Application with Ruby on Rails 7. Second Part: Create a Post Model and a Posts Controller
- Create a Blog Application with Ruby on Rails 7. Third Part: Implement User Authentication
- Create a Blog Application with Ruby on Rails 7. Fourth Part: Performing Operations on the Post Resource
- 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 %>