※2022年から技術系の記事は個人ブログに投稿しております。ぜひこちらもご覧ください→yamaday0u Blog
Railsでフォームを作成するときに使用するform_with
メソッドについて整理しました。
form_withメソッドとは
Railsで用意されているヘルパーメソッドの1つで、投稿ページなどでのフォームの実装に役立ちます。
ヘルパーメソッドとは主にビューでHTMLタグを出現させたりテキストを加工するために使用するメソッドの総称です。
基本構文
form_with
の基本構文は以下の通りです。モデルかスコープかURLは必ず記述します。
form_with(モデル or スコープ or URL [, オプション])
form_withに記述するオプション
他にもいくつかオプションはありますが、ここではよく使うもの紹介します。
オプション | 説明 | デフォルト値 |
---|---|---|
:model | モデルを指定 | |
:scope | スコープを指定 | |
:url | URLを指定 | |
:local | リモート送信の無効 | false |
:method | HTTPメソッドを指定 | POST |
:id | id属性を指定 | |
:class | class属性を指定 |
localオプションについて
:local
はリモート送信(Ajax通信のような非同期通信)によるフォームの送信の有効・無効を設定するオプションです。
JavaScriptでAjax通信によるフォームの送信を実装する場合などは、何も記述しなくてOKです。
逆に、ブラウザの読み込みをするような同期通信を実装する場合は、local: true
と記述して、リモート送信をオフにします。
※参考記事:[Qiita【Rails】form_withに記述するlocal: trueについて]
(https://qiita.com/sho_tsuchida1105/items/b08df35fe3c45f3756da)
form_withメソッドの便利な機能
form_withには、モデル(:model)で記述した場合の便利な機能があります。
引数として渡されたモデルクラスのインスタンスに中身が入っているか否かで、フォーム送信後のアクションをcreateかupdateに自動的に振り分けてくれることです。
インスタンスに中身が入っていない場合はcreateアクションへ、中身が入っている場合はupdateアクションへ処理を振り分けてくれます。
以下のようなfruits_controller.rb
があるとします。
class FruitsController < ApplicationController
before_action :set_fruit, only: [:create, :update]
def index
@fruits = Fruit.all
end
def new
@fruit = Fruit.new# 空のインスタンスを生成
end
def create
redirect_to root_path
end
def edit
@fruit = Fruit.find(params[:id])# URLに含めたidから検索したレコードでインスタンスを生成
end
def update
redirect_to root_path
end
private
def fruit_params
params.require(:fruit).permit(:name, :color)
end
def set_fruit
@fruit = Fruit.create(fruit_params)
end
end
以下のnew.html.erb
とedit.html.erb
は、ほとんど同じ記述ですが、1行目の@fruit
の中身の有無が異なります。
<%= form_with model: @fruit, local: true do |form| %><%# @fruitの中身は空 %>
<div class="">果物の名前</div>
<%= form.text_field :name, class: "item-text-field" %>
<div class="">果物の色</div>
<%= form.text_field :color, class: "item-text-field" %>
<%= form.submit "登録する", class: "submit-btn" %>
<% end %>
<%= form_with model: @fruit, local: true do |form| %><%# @fruitにはeditアクションで代入したレコードの値が入っている %>
<div class="">果物の名前</div>
<%= form.text_field :name, class: "item-text-field" %>
<div class="">果物の色</div>
<%= form.text_field :color, class: "item-text-field" %>
<%= form.submit "更新する", class: "submit-btn" %>
<% end %>
new.html.erb
では、フォームを送信すると@fruit
の中身が空であることを読み取ってcreateアクションに振り分けてくれます。
一方、edit.html.erb
ではフォームを送信すると@fruit
に中身があることを読み取ってupdateアクションに振り分けてくれます。
URLを自分で指定する場合と比べて、モデルのインスタンスを引数として指定することで、記述の手間が減り、フォームの作りをそのまま転用しやすくなります。
form_tagとform_forとの違いについて
従来のform_tag、form_forとの違いについては以下の方が詳しく解説してくれているのでご参照ください。
Railsドキュメント フォーム(form)
Qiita【Rails 5】(新) form_with と (旧) form_tag, form_for の違い