Rails Booklog — 読書ログ(Ruby on Rails + PostgreSQL)

App: https://booklog-qznx.onrender.com/books ※1
GitHub: https://github.com/ynakao55/booklog
※1 サービスが停止している場合は、起動に50秒程かかります。

Ruby on Rails+ PostgreSQL及びRender を使ってブックログサービスを作成・公開しました。
この記事では、アプリの説明/学んだ技術/主要ファイル/Renderでのデプロイ要点をまとめました。
これ一つで、Webアプリ開発の基本要素が一通り体験できます。

目次

1. アプリの説明

1-1. 何をするアプリ?

読んだ本(タイトル/著者/ステータス/メモ)を登録・一覧・詳細表示できるシンプルな読書ログです。
トップのヘッダに [New book] + フィルタ(All / Unread / Reading / Done) をまとめ、下段に一覧テーブルを表示します。Note は一覧では先頭10文字だけ表示(詳細で全文)。

1-2. 主な機能

  • 本の CRUD(登録 / 一覧 / 詳細 / 削除)
  • ステータス管理(enum: unread / reading / done
  • ステータス別フィルタ(クエリ or タブリンク)
  • バリデーション(title / author / status 必須)
  • Note のトリム表示(一覧は10文字 + 省略記号)
  • ベースレイアウトでヘッダ/一覧を視覚分離

1-3. 技術スタック

  • Backend: Ruby on Rails 8.x
  • DB: PostgreSQL
  • Infrastructure: Render(Web Service + Managed PostgreSQL)
  • (Rails 8)Solid Queue / Solid Cache に対応(同一DBロール運用)

2. 学んだ技術とハマりどころ

2-1) Rails 8 の Solid 系(Queue/Cache)

  • 学び: Rails 8はSolid Queue(ジョブ)とSolid Cache(キャッシュ)がデフォルトで読み込まれ、queuecache のDBロールが必要。
  • ハマり: The 'queue' (or 'cache') database is not configured で起動失敗。
  • 対応: config/database.ymlproductionqueue: cache:(さらに cable:)を primary 継承で追加。初回は rails g solid_queue:install / rails g solid_cache:install → migrate。

2-2) Render の接続と起動

  • 学び: Render の DATABASE_URL は本番で ?sslmode=require が必須。
  • ハマり: 無料プランでは Pre-deploy が使えないため、Start Command に db:migrate を連結しないと未マイグレーションで落ちがち。
  • 対応:
    • Start: bundle exec rails db:migrate && bundle exec puma -C config/puma.rb
    • ENV: RAILS_ENV=production / RACK_ENV=production / RAILS_MASTER_KEY or SECRET_KEY_BASE

2-3) enum と Strong Parameters

  • 学び: enumシンボル名文字列で受け取るのが安全(例: "unread")。
  • ハマり: "1" のような数値文字列を直接送ると '1' is not a valid status
  • 対応: フォームの <select> は value を unread/reading/done に。コントローラは permit(:status)

2-4) レイアウトと部分テンプレート

  • 学び: 共通ヘッダ([New book] + フィルタ)と一覧本体を明確に分離すると、UIがすっきり。
  • 実装: application.html.erb(ベース)にヘッダ枠、一覧は books/index.html.erb のテーブルで。

2-5) Note のトリム

  • 学び: ビューで note&.truncate(10) を使うと一発。
  • コツ: nil 耐性のため &. を使う/空文字にはダッシュ等を表示。

3. 主要なファイルの説明(抜粋)

3-1) app/models/book.rb

class Book < ApplicationRecord
  enum status: { unread: 0, reading: 1, done: 2 }
  validates :title, :author, :status, presence: true
end

3-2) app/controllers/books_controller.rb(抜粋)

class BooksController < ApplicationController
  before_action :set_book, only: %i[show destroy]

  def index
    @status = params[:status]
    @books  = if Book.statuses.key?(@status)
                Book.public_send(@status).order(created_at: :desc)
              else
                Book.order(created_at: :desc)
              end
  end

  def new
    @book = Book.new
  end

  def create
    @book = Book.new(book_params)
    if @book.save
      redirect_to books_path(status: params[:status]), notice: "Book created"
    else
      render :new, status: :unprocessable_entity
    end
  end

  def show; end

  def destroy
    @book.destroy
    redirect_to books_path(status: params[:status]), notice: "Book deleted"
  end

  private

  def set_book
    @book = Book.find(params[:id])
  end

  def book_params
    params.require(:book).permit(:title, :author, :status, :note)
  end
end

3-3) app/views/layouts/application.html.erb(ヘッダ分離の例)

<!DOCTYPE html>
<html>
  <head>
    <title>Booklog</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
    <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
  </head>
  <body>
    <header class="container">
      <nav>
        <%= link_to "[New book]", new_book_path, class: "btn" %>
        <span> Filter:
          <%= link_to "All",   books_path %> |
          <%= link_to "Unread",  books_path(status: :unread) %> |
          <%= link_to "Reading", books_path(status: :reading) %> |
          <%= link_to "Done",    books_path(status: :done) %>
        </span>
      </nav>
      <hr>
    </header>

    <main class="container">
      <% if notice %><p class="notice"><%= notice %></p><% end %>
      <%= yield %>
    </main>
  </body>
</html>

3-4) app/views/books/index.html.erb(テーブル + Note トリム)

<h1>Books</h1>

<table>
  <thead>
    <tr>
      <th>Title</th><th>Author</th><th>Status</th><th>Note</th><th></th>
    </tr>
  </thead>
  <tbody>
    <% @books.each do |book| %>
      <tr>
        <td><%= book.title %></td>
        <td><%= book.author %></td>
        <td><%= book.status %></td>
        <td><%= book.note.present? ? book.note.truncate(10) : "—" %></td>
        <td><%= link_to "Show", book_path(book) %></td>
      </tr>
    <% end %>
  </tbody>
</table>

3-5) config/routes.rb

Rails.application.routes.draw do
  root "books#index"
  resources :books, only: %i[index new create show destroy]
end

3-6) config/database.yml(production の Solid ロール)

production:
  primary: &primary
    url: <%= ENV["DATABASE_URL"] %> # ← Render: 末尾に ?sslmode=require
    pool: <%= ENV.fetch("RAILS_MAX_THREADS", 5) %>

  queue:
    <<: *primary

  cable:
    <<: *primary

  cache:
    <<: *primary

3-7) config/environments/production.rb(一例)

# Solid Cache を使わずメモリにしたい場合(暫定)
# config.cache_store = :memory_store

# ジョブを使わず async にしたい場合(暫定)
# config.active_job.queue_adapter = :async

4. Render デプロイの要点(チェックリスト)

4-1) GitHub に push 済み?

  • ✅ main ブランチにコミット&Push

4-2) Render で Web Service 作成

  • ✅ リポジトリを選択
  • ✅ Free PG を作成済み(または既存PGを使う)

4-3) Environment Variables

  • RAILS_ENV=production / RACK_ENV=production
  • DATABASE_URL=postgresql://USER:PASS@HOST:PORT/DB?sslmode=require
  • RAILS_MASTER_KEY or SECRET_KEY_BASE
  • ⭕(推奨)RAILS_LOG_TO_STDOUT=true, RAILS_SERVE_STATIC_FILES=true

4-4) Start Command(無料プラン想定)

bundle exec rails db:migrate && bundle exec puma -C config/puma.rb

4-5) Solid Queue / Cache

  • config/database.ymlqueue/cache/cable 追加
  • ✅ 初回のみ rails g solid_queue:install / rails g solid_cache:install → migrate

4-6) よくある落とし穴

  • ?sslmode=require を付け忘れる
  • Pre-Deploy が使えない → Start に db:migrate を連結
  • enum の値に数字文字列を渡してエラー('1' is not a valid status

5. スクリーンショット

5-1)トップページ


5-2)新規追加ページ

5-3)詳細ページ

6. まとめ

Rails 8 + PostgreSQL で作る最小構成の読書ログです。
Render へのデプロイでは queue/cache/cable のDBロールStart Command での migrate がポイント。
ポートフォリオとして、「Railsで作って実環境にデプロイ」までを一気通貫で示せるように仕上げました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

目次