Chapter 10: Blog Project Part 2 – Comments and Associations

Chapter 10: Blog Project Part 2 – Comments and Associations

AI Reading

Quick summary of this article

Preparing the AI summary…

Chapter 10: Blog Project Part 2 – Comments and Associations

In Chapter 8 you built a complete blog where you can create, read, update, and delete posts. In this chapter we will make it a realistic application by adding comments. Each comment belongs to a post, which introduces the most important Rails concept after CRUD: associations.

In this chapter you will learn how to connect models with has_many and belongs_to, generate a Comment model, and display and add comments on a post.

🔗 What are Associations?

Associations tell Rails how two models are related. For our blog, a Post has many Comments, and a Comment belongs to a Post. This one-to-many relationship is the foundation of most real applications.

# app/models/post.rb
class Post < ApplicationRecord
  has_many :comments, dependent: :destroy
end
# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :post
end

The dependent: :destroy option means that when a post is deleted, its comments are deleted too, which keeps your database clean.

💾 Generating the Comment Model

Generate a Comment model that belongs to a Post and has a body field:

rails generate model Comment post:references body:text
rails db:migrate

The post:references type automatically adds a post_id column to the comments table and an index on it, which is exactly what the association needs.

# db/migrate/xxx_create_comments.rb
class CreateComments < ActiveRecord::Migration[7.0]
  def change
    create_table :comments do |t|
      t.references :post, null: false, foreign_key: true
      t.text :body

      t.timestamps
    end
  end
end

🚀 Creating Comments in the Console

With the association set up, Rails gives you helpful methods. Open the console and try them:

rails console
# Find a post and add a comment to it
post = Post.first
post.comments.create(body: "Great tutorial, thanks!")

# Count comments on the post
post.comments.count

# Find the post a comment belongs to
comment = Comment.first
comment.post.title

Rails automatically fills in the post_id for you when you create a comment through post.comments.create.

📝 Showing Comments in the View

Open app/views/posts/show.html.erb and display the post’s comments by looping over them:

<h3>Comments (<%= @post.comments.count %>)</h3>

<% @post.comments.each do |comment| %>
  <p><strong><%= comment.body %></strong></p>
  <p><small>Posted on <%= comment.created_at.strftime("%B %d, %Y") %></small></p>
  <hr>
<% end %>

✍️ Adding a Comment Form

Add a simple form below the comments list so visitors can leave a new comment:

<h3>Leave a Comment</h3>
<%= form_with model: [ @post, @post.comments.build ] do |form| %>
  <div>
    <%= form.label :body %><br>
    <%= form.text_area :body, rows: 4 %>
  </div>
  <%= form.submit "Post Comment" %>
<% end %>

For the form to work, add a create action to the controller and a nested route:

# app/controllers/comments_controller.rb
class CommentsController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(comment_params)
    redirect_to @post
  end

  private

  def comment_params
    params.require(:comment).permit(:body)
  end
end
# config/routes.rb
resources :posts do
  resources :comments, only: [:create]
end

🏠 Practice Exercises

# 1. Generate the Comment model
rails generate model Comment post:references body:text
rails db:migrate
# 2. Set up the associations
# app/models/post.rb
class Post < ApplicationRecord
  has_many :comments, dependent: :destroy
end

# app/models/comment.rb
class Comment < ApplicationRecord
  belongs_to :post
end
# 3. Test in the console
post = Post.first
post.comments.create(body: "First comment!")
post.comments.count  # => 1
post.comments.map(&:body)

You have now connected two models with a real database relationship. Associations open the door to building applications like a Twitter-style feed, an e-commerce store with orders and line items, or any app where data is related. In the next chapter you will learn how to secure your app with authentication.

Leave a Reply

Your email address will not be published. Required fields are marked *