見積書をExcelで作り、受注したら別のExcelで請求書を作り、入金は通帳を見ながら手で消し込む。多くの会社で続いているこのやり方を、自社で小さなシステムに置き換えたい。そう考えたとき、「Ruby on Rails 8で、見積・請求管理システムを作る」連載を始めます。
「見積と請求がExcelと紙でバラバラ。システムにしたいけど、何から始めればいいのか分からない」
結論から言うと、Rails 8 は「少人数で業務システムを作る」ための部品が最初からそろっていて、最初の1画面は30分ほどで動きます。 この第0回では、完成像とスタックの選定理由を説明し、実際に雛形を作ってトップページとヘルスチェックのテストまで通します。
この連載は、発注側の社内エンジニア・情シス担当者と、これから見積・請求システムを依頼する発注者の方の両方を読者に想定しています。プログラミング経験があれば、Rubyが初めてでも追えるように書きます。
見積・請求管理システムで作るもの(完成像)
連載の最後には、次の機能がそろった小さな業務システムになります。
| 回 | 作る機能 |
|---|---|
| 1 | 取引先・品目のマスタ管理 |
| 2 | ログインと権限(Rails標準の認証) |
| 3〜4 | 見積書・明細の作成、消費税と端数処理の計算 |
| 5〜6 | 見積書のPDF出力、メール送信の非同期化 |
| 7〜8 | 受注から請求書への変換、入金管理と督促一覧 |
| 9 | Kamalでサーバーへ配備 |
Excelでの運用が限界を迎えるのは、たいてい「最新版がどれか分からない」「計算ミスが起きる」「誰がいつ変更したか追えない」という3点です。システム化の価値は、この3点を仕組みで防げるところにあります。
なぜRails 8を選ぶのか:業務システム向きの3つの理由
Rails 8 は2024年11月に公開されました。本連載で使う8.1系は、RubyGemsの記録では2025年10月22日に初版が公開されています(執筆時点の2026年10月は、8.1.4を使用)。
📰 出典:Rails 8.0: No PaaS Required(Ruby on Rails公式ブログ)
理由1:外部サービスを増やさずに済む
以前のRailsは、ジョブ(非同期処理)やキャッシュのためにRedisという別のサーバーが必要でした。Rails 8では、Solid Queue(処理待ちの管理)・Solid Cache(キャッシュ)・Solid Cable(リアルタイム通信) がデータベースだけで動く標準部品になりました。
発注者にとっては「構成部品が少ない=運用で気にすることが少ない」ということです。後の回で、見積書のメール送信を非同期にするときにSolid Queueを使います。
理由2:画面づくりの量が少ない(Hotwire)
Hotwire(ホットワイヤー)は、画面を丸ごと作り直さずに、必要な部分だけ書き換える仕組みです。見積書に明細行を追加する画面などを、JavaScriptをほとんど自作せずに作れます。
理由3:配備の道具が標準で付いている
Rails 8には、サーバー1台へDockerイメージを配備するKamal 2が標準で含まれます。本連載では最終回でKamalを使います。連載済みのECSやCloud Runとの違いも、そこで整理します。
開発環境をそろえて雛形を作る
今回の検証環境は、Ruby 3.3系・PostgreSQL 16です。Rails 8.1はRuby 3.2以上が必要です。PostgreSQLは、業務データの扱いでSQLiteより選ばれやすい標準的な選択として、開発・本番とも使います。
まず、Railsを入れて雛形を作ります。
gem install rails -v "~> 8.1"
rails new code --database=postgresql --skip-git --skip-kamal --skip-docker
rails new はプロジェクトの骨組みを自動生成するコマンドです。--database=postgresql でデータベースにPostgreSQLを指定しています。--skip-kamal・--skip-docker は、第9回でまとめて扱うため今回は外しています。
データベース接続を環境変数で切り替える
生成された設定のままだと、接続先がマシンごとに違うときに困ります。接続先は環境変数で上書きできるようにします。
# config/database.yml(抜粋)
default: &default
adapter: postgresql
encoding: unicode
max_connections: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: <%= ENV.fetch("DB_HOST", "localhost") %>
username: <%= ENV.fetch("DB_USER", "postgres") %>
password: <%= ENV.fetch("DB_PASSWORD", "postgres") %>
本番のパスワードは、コードに書かず環境変数(MITSUMORI_DATABASE_PASSWORD)から読みます。この連載では、秘密情報をコードや記事に載せないルールで進めます。
トップページを1枚作り、日本語向けに設定する
画面を1枚だけ作って、動作を確認します。コントローラーとビューを生成し、ルーティングでトップページに設定します。
# config/routes.rb(抜粋)
Rails.application.routes.draw do
get "up" => "rails/health#show", as: :rails_health_check
root "home#index"
end
<%# app/views/home/index.html.erb %>
<h1>見積・請求管理システム</h1>
<p>見積書を作り、受注後に請求書へ変換し、入金状況まで管理するサンプルです。</p>
get "up" は、Railsが最初から用意しているヘルスチェック(生きているかの確認)用のURLです。サーバーの監視や、後で扱うKamalの配備でも使われます。
あわせて、タイムゾーンと表示言語を日本向けにします。
# config/application.rb(抜粋)
config.time_zone = "Tokyo"
config.i18n.default_locale = :ja
見積書や請求書は日付が命です。タイムゾーンを最初に決めておかないと、日付がずれる不具合につながります。
テストを最初から書く
業務システムは、あとから金額計算などを変えたときに壊れていないか確かめられることが重要です。第0回から、Rails標準のMinitestでテストを置きます。
# test/controllers/home_controller_test.rb
require "test_helper"
class HomeControllerTest < ActionDispatch::IntegrationTest
test "トップページが表示される" do
get root_url
assert_response :success
assert_select "h1", "見積・請求管理システム"
end
test "ヘルスチェックが応答する" do
get rails_health_check_url
assert_response :success
end
end
動作確認
データベースを作り、テストと静的チェック(RuboCop)を実行します。
bin/rails db:prepare
bin/rails test
bundle exec rubocop
私の検証環境では、テスト2件が成功し、RuboCopの指摘は0件でした。次に bin/rails server で起動してブラウザで開くと、次の画面になります。


※Linuxの開発環境で撮影したため、お使いのOSやブラウザとは見た目が異なる場合があります。
つまずきやすい点
- Bundlerをrootで実行しない:警告が出て、他のユーザーで動かなくなることがあります。普通のユーザーで実行してください。
- PostgreSQLに接続できない:サーバーが起動しているか、
DB_USER・DB_PASSWORDが合っているかを確認します。 - Rubyのバージョン:Rails 8.1はRuby 3.2以上が前提です。古いRubyのままだとインストールで止まります。
発注者向けメモ:Railsで業務システムを頼むときの確認点
この連載の内容を、開発会社に見積・請求システムを依頼する立場で見ると、次の点を確認しておくと安心です。
- ☐ 使うフレームワークとバージョン(今回なら Rails 8系)と、保守の期限を説明してもらえるか
- ☐ テストコードが納品物に含まれ、金額計算がテストで固定されているか
- ☐ 秘密情報(パスワード等)が、ソースコードに直接書かれていないか
- ☐ インボイス制度や電子帳簿保存法への対応範囲を、どこまで作るか事前に合意しているか
- ☐ 本番環境の構成(サーバー台数・データベース・バックアップ)と、月々の運用費の内訳が示されるか
税や法令の扱いは、一般論と実務の判断が異なる場合があります。個別の判断は、顧問の税理士などにご相談ください。
なお、この回の環境では、本番サーバーへの配備やメール送信は行っておらず、未確認です。該当する回で、確認できた範囲と未確認の範囲を明記します。
まとめと次回予告
第0回では、Rails 8の特長(Solid Queueなど)と、見積・請求管理システムの完成像を整理しました。そのうえで、PostgreSQLを使うRails 8の雛形を作り、トップページ・ヘルスチェック・テストまで通しました。
次回の第1回は「取引先と品目のマスタを作る」です。scaffoldを使って、入力チェック付きの登録・一覧画面を作ります。
この連載の記事一覧
この記事は連載「Railsで作る見積・請求管理システム」の1回です。連載のほかの回は次のとおりです(連載の一覧ページ)。
- 【Railsで作る見積・請求管理システム 第0回】Rails 8の雛形を動かして、Excel見積からの脱却を始める(この記事)
- 【Railsで作る見積・請求管理システム 第1回】取引先と品目のマスタを作る(scaffoldと入力チェック)
- 【Railsで作る見積・請求管理システム 第2回】ログインを付ける(Rails 8標準の認証と権限の分け方)
- 【Railsで作る見積・請求管理システム 第3回】見積書と明細を作る(Hotwireで明細行をその場で追加)
- 【Railsで作る見積・請求管理システム 第4回】金額・消費税・端数処理を正しく計算する(税率ごとに1回だけ丸める)
- 【Railsで作る見積・請求管理システム 第5回】見積書をPDFで出力する(Prawnで日本語フォントを扱う)
- 【Railsで作る見積・請求管理システム 第6回】見積書をメールで送る(Solid Queueで送信を非同期にする)
- 【Railsで作る見積・請求管理システム 第7回】受注から請求書へ変換する(状態遷移と請求番号、インボイスの記載事項)
- 【Railsで作る見積・請求管理システム 第8回】入金管理と督促の一覧を作る(一部入金・期限超過の抽出)










コメント
コメント一覧 (6件)
[…] 【Railsで作る見積・請求管理システム 第0回】Rails 8の雛形を動かして、Excel… […]
[…] 見積書を作る前に、まず「誰に」「何を」売るのかを登録しておく土台が要ります。この第1回では、Ruby on Rails 8の scaffold を使って、取引先マスタと品目マスタの登録・一覧画面を作り、入力チェックと日本語化まで仕上げます。前回の第0回(Rails 8の雛形を動かして、Excel見積からの脱却を始める)で作った雛形の続きです。 […]
[…] 【Railsで作る見積・請求管理システム 第0回】Rails 8の雛形を動かして、Excel… […]
[…] 【Railsで作る見積・請求管理システム 第0回】Rails 8の雛形を動かして、Excel… […]
[…] 【Railsで作る見積・請求管理システム 第0回】Rails 8の雛形を動かして、Excel… […]
[…] 【Railsで作る見積・請求管理システム 第0回】Rails 8の雛形を動かして、Excel… […]