rails ブログ機能の実装方法7選【Rails 8対応・コード実例付き】

  • このエントリーをはてなブックマークに追加

スポンサーリンク

「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.