「Railsでブログ機能を作ってみたいけれど、どこから手をつければいいのか分からない」——そんな経験はありませんか?ブログは、記事の一覧・詳細・投稿・編集といった Web アプリの基本がひととおり詰まっているので、Rails 学習の題材としてとても優秀です。
この記事では、Rails 初心者の方がブログ機能を実装できるようになるための方法を、コピペで動くコード例つきで7つ紹介します。記事一覧の表示から、投稿・編集・カテゴリ・コメント・公開/非公開の切り替えまで、よく使う機能を順番に解説していきます。
コードは現行の Rails 8(8.1 系)で動作する書き方に揃えています。Rails 7 でもほぼそのまま使えます。まだ環境がない方は、macOSにRuby on Railsをインストールを先に済ませておくとスムーズです。
最短で作るなら scaffold、でも中身を理解したいなら手で作る
先に補足しておくと、記事の CRUD(作成・表示・更新・削除)だけなら rails g scaffold Post title:string body:text の一発でも生成できます。ただ、生成されたコードの意味が分からないまま進むと、後で詰まりがちです。
そこでこの記事では、各機能を「なぜ必要か」「どのコードが何をしているか」まで分解して解説します。仕組みが分かれば、scaffold で作ったコードも自信を持って読めるようになります。
1. 記事の一覧を表示する
ブログの入り口になるのが、記事一覧ページです。読者はまず「どんな記事があるか」を確認したいので、ここが分かりにくいと離脱につながります。
Railsでは、次の手順で実装します。
- 記事(Post)モデルを作成する
- コントローラで投稿データをまとめて取り出す(
Post.all) - 一覧ページ(
index.html.erb)で記事を順番に表示する - タイトルと投稿日を見せると分かりやすい
記事を新しい順に並べたいときは Post.order(created_at: :desc) を使います。
# app/controllers/posts_controller.rb
def index
@posts = Post.order(created_at: :desc)
end<!-- app/views/posts/index.html.erb -->
<h1>記事一覧</h1>
<% @posts.each do |post| %>
<div>
<h2><%= link_to post.title, post_path(post) %></h2>
<p><%= post.created_at.strftime('%Y年%m月%d日') %></p>
</div>
<% end %>これで、タイトル(リンク付き)と投稿日が新しい順に並びます。記事が増えてきたら kaminari などのgemでページネーションを足すと、一覧が長くなりすぎず快適です。
2. 記事の詳細ページを作る
一覧ページだけではタイトルしか見えません。本文を読むには、1記事を表示する詳細ページが必要です。
詳細ページは次の流れで作ります。
- コントローラで
showアクションを用意する - URLに記事のID(
params[:id])を含めてアクセスできるようにする - ページ内でタイトルと本文を表示する
- 必要なら作成日・更新日・カテゴリーも表示する
@post = Post.find(params[:id]) で、URLで指定された記事を1件取得できます。
# app/controllers/posts_controller.rb
def show
@post = Post.find(params[:id])
end<!-- app/views/posts/show.html.erb -->
<h1><%= @post.title %></h1>
<p><%= @post.created_at.strftime('%Y年%m月%d日') %></p>
<div>
<%= simple_format(@post.body) %>
</div>simple_format は、本文の改行を <br> や <p> に変換して表示するヘルパーです。見出しや太字なども使える本格的なエディタにしたい場合は、Rails 標準の ActionText(リッチテキスト機能)を検討するとよいでしょう。
3. 新しい記事を作成できるようにする
記事を追加できる機能があると、ブログは育っていきます。ここでは投稿フォームと、その内容を保存する処理を作ります。
- 投稿ページ(
new.html.erb)を作る - 入力フォームを用意する(
form_with model: @post) - コントローラの
createアクションで内容を保存する - 保存後、一覧や詳細ページに移動させる
# app/controllers/posts_controller.rb
def new
@post = Post.new
end
def create
@post = Post.new(post_params)
if @post.save
redirect_to @post
else
render :new, status: :unprocessable_content
end
end
private
def post_params
params.require(:post).permit(:title, :body)
end<!-- app/views/posts/new.html.erb -->
<h1>新しい記事を作る</h1>
<%= form_with model: @post do |form| %>
<p>タイトル:<br><%= form.text_field :title %></p>
<p>本文:<br><%= form.text_area :body %></p>
<%= form.submit '投稿する' %>
<% end %>2点、初心者がつまずきやすいポイントを補足します。
- ブロック変数名は揃える:
form_with model: @post do |form|と書いたら、中でもform.submitのように同じformを使います。|form|なのにf.submitと書くと「undefined local variable」でエラーになります。 - 保存失敗時のステータス:バリデーションで保存に失敗したら 422 を返します。Rails 8(Rack 3.1 以降)では
:unprocessable_contentが正式名です。Rails 7 など古い環境では、これまでどおり:unprocessable_entityを使ってください(どちらも 422 を返します)。
4. 記事を編集・削除する機能をつける
投稿後の記事を、あとから直したり消したりできるようにしましょう。誤字の修正や、公開をやめたい記事の削除など、運用では必ず必要になります。
- 編集ページ(
edit.html.erb)と削除ボタンを用意する - 編集は
update、削除はdestroyアクションを使う - 入力内容で記事を上書きする(
@post.update(post_params)) - 削除は
@post.destroyを呼ぶ
# app/controllers/posts_controller.rb
def edit
@post = Post.find(params[:id])
end
def update
@post = Post.find(params[:id])
if @post.update(post_params)
redirect_to @post
else
render :edit, status: :unprocessable_content
end
end
def destroy
@post = Post.find(params[:id])
@post.destroy
redirect_to posts_path
end<!-- app/views/posts/show.html.erb に追加 -->
<%= link_to '編集', edit_post_path(@post) %> |
<%= button_to '削除', @post, method: :delete, data: { turbo_confirm: '本当に削除しますか?' } %>data: { turbo_confirm: ... } を付けると、削除前に確認ダイアログが出ます。Rails 7 以降は Turbo が標準なので、この書き方で誤操作を防げます。
5. カテゴリーで記事を分ける
記事をテーマ別に分けると、読者が読みたい内容を探しやすくなります。ここでは記事とカテゴリを関連付ける方法を見ていきます。
- カテゴリ(Category)モデルを作る
- 記事とカテゴリを関連付ける(
belongs_to/has_many) - 投稿時にカテゴリを選べるようにする
- カテゴリ別の一覧ページを用意する
@category.posts で、そのカテゴリに属する記事だけを取り出せます。
# app/models/category.rb
has_many :posts
# app/models/post.rb
belongs_to :category<!-- app/views/posts/new.html.erb に追加 -->
<p>カテゴリー:<br>
<%= form.collection_select :category_id, Category.all, :id, :name %>
</p>collection_select は、カテゴリ一覧からプルダウンを自動生成してくれるヘルパーです。post_params に :category_id を追加するのを忘れないようにしましょう(許可していないと保存されません)。
6. コメント機能をつける
読者が感想を書けるようにすると、ブログに交流が生まれます。記事(Post)1件に対してコメント(Comment)が複数ぶら下がる、1対多の関連で作ります。
- コメント(Comment)モデルを作る
- 記事とコメントを関連付ける(
belongs_to/has_many) - 詳細ページにコメント一覧を表示する
- その下にコメント投稿フォームを置く
# app/models/comment.rb
belongs_to :post
# app/models/post.rb
has_many :comments, dependent: :destroy<!-- app/views/posts/show.html.erb の下部に追加 -->
<h2>コメント</h2>
<% @post.comments.each do |comment| %>
<div>
<strong><%= comment.name %></strong>:<%= comment.content %>
</div>
<% end %>
<h3>コメントを書く</h3>
<%= form_with model: [@post, @post.comments.build] do |form| %>
<p>お名前:<br><%= form.text_field :name %></p>
<p>内容:<br><%= form.text_area :content %></p>
<%= form.submit '送信' %>
<% end %>has_many :comments, dependent: :destroy としておくと、記事を削除したときに紐づくコメントも一緒に消えます(これを付けないと、行き場のないコメントがDBに残ります)。なお、ログインなしで誰でも投稿できるコメントは、スパム対策(reCAPTCHA など)を後から足すことも検討しましょう。
7. 公開・非公開の切り替え機能をつける
「書きかけの記事は下書きにしておきたい」「準備ができたら公開したい」——そんなときに使うのが公開/非公開の切り替えです。
一番シンプルなのは、真偽値のカラム(is_published)を1つ足す方法です。
# migration で追加
add_column :posts, :is_published, :boolean, default: false, null: false
# app/controllers/posts_controller.rb(一覧では公開記事だけ表示)
@posts = Post.where(is_published: true).order(created_at: :desc)<!-- new / edit のフォームに追加 -->
<p>
公開する?<br>
<%= form.check_box :is_published %> はい
</p>将来「予約公開」「アーカイブ」など状態を増やしたくなりそうなら、真偽値ではなく enum で管理する方が拡張しやすいです。Rails 8 なら次のように書けます。
# add_column :posts, :status, :integer, default: 0, null: false
# app/models/post.rb
enum :status, { draft: 0, published: 1, archived: 2 }
# 使い方
post.published! # 公開状態に変更
Post.published # 公開記事だけ取得(scope が自動生成される)enum を使うと Post.published のようなスコープや post.published? といった判定メソッドが自動で生えるので、コードが読みやすくなります。
まとめ:さらにステップアップするために
ここまで、Railsでブログ機能を作る基本を7つ紹介しました。一覧・詳細・投稿・編集削除・カテゴリ・コメント・公開切替まで実装できれば、ブログアプリの土台は完成です。
実務では「もっと読みやすく」「もっと安全に」するために、コードの整理や機能強化が必要になります。仕上げにおすすめの3つを紹介します。
1. before_action でコードをすっきりさせる
各アクションで Post.find(params[:id]) を何度も書くと、コードが重複します。共通の前処理は before_action にまとめましょう。
before_action :set_post, only: [:show, :edit, :update, :destroy]
private
def set_post
@post = Post.find(params[:id])
endこれで、対象アクションの @post = Post.find(params[:id]) をすべて削除できます。重複が減り、修正も1ヶ所で済みます。
2. フォームを部分テンプレートで共通化する
新規作成ページと編集ページは、ほぼ同じフォームを使います。_form.html.erb という共通ファイルに切り出して、両方から読み込みましょう。
<%= render 'form', post: @post %>フォームを直すときも1ヶ所を修正すれば、新規・編集の両方に反映されます。
3. 管理者だけが記事を投稿できるようにする(認証の導入)
投稿・編集を特定の人だけに許可したいなら、ログイン機能が必要です。Rails 8 では認証ジェネレータ(rails g authentication)が標準で用意されており、devise gem を使う選択肢もあります。
どちらを選ぶかは、Rails 8の認証ジェネレータとDeviseはどっちを使う?で違いと判断基準を解説しています。ログイン必須にするには、コントローラに次の1行を足します(メソッド名は使う仕組みに合わせてください)。
# devise の場合
before_action :authenticate_user!, except: [:index, :show]これで、ログインしていない人が投稿ページにアクセスすると、自動的にログインページへ戻されます。見た目を整えたい方は RailsにTailwind CSS v4を導入する方法もあわせてどうぞ。エラーで手が止まったときは、エンジニアの仕事は「知っていること」より「調べられること」も参考になります。
スポンサーリンク

コメント
Comments are closed.