0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Next.js + Railsでのフォームのバリデーションについて

0
Posted at

概要

Next.js(App Router)と Rails API を組み合わせた構成でWebアプリを作成した場合、

  • フロントエンドとバックエンド両方でバリデーションしたい
  • 最終的な正しさはサーバーで保証したい
  • バリデーションロジックの二重管理は避けたい

と考えることが普通かと思います。
そこで、ここでは、

  • Zod を用いた Next.js 側のバリデーション
  • Rails 側で担保すべき責務
  • どこまでをフロントで、どこからをバックエンドで行うべきか

を、実例ベースで整理しようと思います。


想定構成

  • Frontend: Next.js (App Router)
  • Validation: Zod + react-hook-form
  • Backend: Rails (API Mode)

フロントエンド(Next.js)でのバリデーション責務

フロントエンドのバリデーションは「UX向上」が目的として考えられます。

  • 入力ミスを即座にユーザーへ伝える

  • 無駄な API リクエストを減らす

  • UI側と密結合な制約を扱う

Zod を使ったスキーマ定義例

import { z } from "zod";

export const contactSchema = z.object({
  name: z
    .string()
    .min(1, "名前が入力されていません。")
    .max(16, "最大16文字までです。"),

  email: z
    .string()
    .min(1, "メールアドレスが入力されていません。")
    .email("メールアドレスの形式で入力してください。"),

  subject: z
    .string()
    .min(1, "件名が入力されていません。")
    .max(50, "最大50文字までです。"),

  message: z
    .string()
    .min(1, "本文が入力されていません。")
    .max(200, "最大200文字までです。"),
});

export type ContactFormValues = z.infer<typeof contactSchema>;

フロントで行うべきバリデーションの例

種類
必須チェック 空文字、未入力
形式チェック email, URL
文字数制限 max/min
UI依存 利用規約チェック、確認チェック

これらは Zod + react-hook-form で即時フィードバックするのが最適です。

Rails(バックエンド)でのバリデーション責務

Rails 側は「信頼できない入力」を前提にします。

  • フロントのバリデーションは 必ず突破される
  • API は curl / Postman / 改ざんリクエストを想定する
  • DB整合性・業務ルールはすべてサーバーで担保する

Rails 側で必須なバリデーション例

class Contact < ApplicationRecord
  validates :name, presence: true, length: { maximum: 16 }
  validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }
  validates :subject, presence: true, length: { maximum: 50 }
  validates :message, presence: true, length: { maximum: 200 }
end

Rails でしかできないバリデーション

種類
DB依存 unique制約
業務ルール 同一メールの送信回数制限
認可 ログインユーザーのみ送信可
状態依存 ステータスによる制限

これらは フロントに置いてはいけません。


## 二重管理への考え方
  • 結論:二重管理は「避けられない」
    TS / Ruby 間でのコード共有は現実的ではありません。よってFEではUX改善を、BEではデータの正当性を保証するというう目的で、制約を分割して考えるべきです。

バリデーション目的がそもそも違う

実務でのおすすめ分割

コードをコピーする
Zod(Next.js)
├─ 必須
├─ 形式
├─ 文字数
└─ UX向上用

Rails
├─ 必須
├─ 形式
├─ 文字数
├─ 業務ロジック
├─ 認可
└─ DB制約

エラーハンドリングの流れ

  • Zod で即時エラー表示

  • OKなら API 送信

  • Rails で最終検証

  • Rails のエラーを UI に反映


まとめ

FEとBEのバリデーション責務に関しては、ZodはUX のため
Railsは正しさのために分割を行うことがよいと考えています。
このように役割を分ければ、二十に管理している部分があったとしても、保守性はむしろ上がります。

ここでの、Next.js + Rails 構成では、それぞれの役割を分割することで、より適切なバリデーション分割を考えました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?