みなさん、こんにちは。
前回は、ビューとヘルパーの役割を整理し、画面に表示する処理をどこまでビューに書くべきかを考えました。今回はその流れを受けて、「フォーム」と「バリデーション表示」を扱います。
フォームはユーザーから入力を受け取るための入り口ですが、Railsでは単なるHTMLではありません。モデル、ルーティング、コントローラ、ビューが連携し、入力、検証、保存、再表示という一連の流れを作ります。試験でも form_with、params、Strong Parameters、errors、render と redirect_to の違いは関連して問われやすい重要テーマです。
実務でも、フォームの設計は使いやすさに直結します。入力に失敗したときに値を残し、どこを直せばよいかを伝えることは、Railsらしい責務分担を理解するうえでも大切です。
form_withの基本
Rails 7.1でフォームを作るときの基本は form_with です。特にモデルに紐づくフォームでは、model: にオブジェクトを渡します。
| <%= form_with model: @article do |form| %> <%= form.label :title %> <%= form.text_field :title %> <%= form.label :body %> <%= form.text_area :body %> <%= form.submit %> <% end %> |
@article が新規レコードなら作成用、既存レコードなら更新用として、RailsがURLやHTTPメソッドを推測します。つまり、規約に沿っておけば細かな設定を書きすぎなくてもよい、という Rails の規約がここにも表れています。
古い教材では form_for や form_tag を見ることがありますが、Rails 7.1の新しいコードでは form_with を理解しておくとよいでしょう。
保存失敗時はrenderで戻す
フォームから送信された値は params に入り、Strong Parameters で許可した項目だけをモデルに渡します。保存の成否で画面遷移を分ける典型的なコードを見てみましょう。
| def create @article = Article.new(article_params) if @article.save redirect_to @article, notice: “記事を作成しました” else render :new, status: :unprocessable_entity end end private def article_params params.require(:article).permit(:title, :body) end |
ここで重要なのは、失敗時に redirect_to ではなく render :new を使う点です。redirect_to は別のリクエストになるため、入力途中の @article やエラー情報が失われやすくなります。一方、render は同じリクエストの中で new テンプレートを表示するため、@article.errors をビューで使えます。
Rails 7系では status: :unprocessable_entity を付ける書き方もよく使われます。これはHTTPステータス422を返し、「リクエストは理解できたが、入力内容として処理できなかった」ことを表します。
エラー表示の考え方
バリデーションはモデルに書きます。ビューで入力値を直接判定するのではなく、モデルが持つ errors を表示します。
| <% if @article.errors.any? %> <ul> <% @article.errors.full_messages.each do |message| %> <li><%= message %></li> <% end %> </ul> <% end %> |
errors.any? はエラーの有無を確認し、errors.full_messages は属性名を含むメッセージを返します。入力欄の近くに表示したい場合は full_messages_for(:title) のように属性ごとのエラーを取り出すこともできます。
また、@article = Article.new(article_params) として作ったオブジェクトを render :new で再利用するため、ユーザーが入力した値もフォームに残ります。フォームとモデルオブジェクトを結びつける意味は、送信先の推測だけでなく、再表示のしやすさにもあります。
フォームはpartialに切り出す
新規作成画面と編集画面では、同じフォームを使うことが多くあります。その場合は _form.html.erb のようなpartialに切り出すと、コードの重複を減らせます。
| <%= render “form”, article: @article %> <!– _form.html.erb –> <%= form_with model: article do |form| %> … <% end %> |
partial内で直接 @article に依存するより、article: @article のようにローカル変数として渡すと、どのデータを使う部品なのかが分かりやすくなります。DRYを守りながら、ビューの見通しもよくなります。
模擬問題
問題1
次のうち、Rails 7.1でモデルに紐づいたフォームを作成する方法として最も適切なものを1つ選びなさい。
1. form_for @article do |form|
2. form_tag articles_path do
3. form_with model: @article do |form|
4. html_form model: @article do |form|
正解
3
解説
Rails 7.1では form_with が基本です。model: を指定すると、Railsは新規作成か更新かを判断してURLやHTTPメソッドを推測します。1と2は古い教材で見ることがありますが、現在の基本としては3を使います。4はRails標準のヘルパーではありません。
問題2
バリデーションに失敗したとき、入力値とエラーメッセージを保持してフォームを再表示する実装として最も適切なものを1つ選びなさい。
1. redirect_to new_article_path
2. render :new, status: :unprocessable_entity
3. redirect_to articles_path, status: :unprocessable_entity
4. render :show
正解
2
解説
保存に失敗した @article をそのまま使って new テンプレートを表示するため、render :new が適切です。redirect_to は別リクエストになるので、通常は入力値や errors が失われます。render :show は作成に失敗したレコードの詳細表示として不自然です。
問題3
新規作成画面と編集画面で同じ記事フォームを使う場合、Railsらしい設計として最も適切なものを1つ選びなさい。
1. new.html.erb と edit.html.erb に同じHTMLをコピーする
2. コントローラ内でHTML文字列を組み立てる
3. _form.html.erb partialに切り出し、article: @article のように渡す
4. ビュー内で入力値を直接判定してバリデーションする
正解
3
解説
共通フォームはpartialに切り出すとコードの重複を減らせます。ローカル変数で渡すと依存関係も明確です。1は変更漏れを招き、2はMVCの責務分担から外れます。4は入力ルールをモデルではなくビューに置いてしまうため、Railsらしい設計ではありません。
まとめ
今回は、Rails 7.1におけるフォームとバリデーション表示を整理しました。form_with はHTMLを作るだけでなく、モデルオブジェクトと結びつくことで、送信先の推測、入力値の保持、エラー再表示までを自然に支えます。
試験では、form_with の基本、params と Strong Parameters、保存失敗時の render、errors.full_messages の使い方が重要です。実務では、ユーザーが迷わず入力を修正できる画面を作ることが、Railsの責務分担を守ることにもつながります。
次回は、フォームの裏側でデータを扱う中心的な仕組みである Active Record の基礎を取り上げます。モデルがデータベースとどのようにつながるのかを見ていきましょう。
Rails7認定ベーシック試験について
全国300か所で通年実施しています。詳細は以下をご覧ください。

また、450ページを超える教科書も安価に出版しています。学習にあたってご活用ください。詳細は以下をご覧ください。
Rails 7 技術者認定ベーシック試験公式教科書ベータ版
著者:小澤昌樹 発行:Rails技術者認定試験運営委員会
価格(税込):ペーパーバック版 2,497円 Kindle版 1250円
ページ数:471ページ


