LoginSignup
1
0

【Ruby on Rails】form_withヘルパーを押さえる

Last updated at Posted at 2024-03-03

対象読者(学習前の自分)

  • rails初学者
  • form_withヘルパーを魔術に感じている方

form_withヘルパーでできること

フォームの自動生成。
こんなコードを書くと...

_form.html.erb
<%= form_with(model: @user) do |form| %>

  <%= form.label :name %>
  <%= form.text_field :name, class: 'form-control' %>

  <%= form.label :email %>
  <%= form.email_field :email, class: 'form-control' %>

  <%= form.label :password %>
  <%= form.password_field :password, class: 'form-control' %>

  <%= form.label :password_confirmation, "Confirmation" %>
  <%= form.password_field :password_confirmation, class: 'form-control' %>

  <%= form.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>

このようにフォームを生成してくれる
image.png

編集ページならデフォルト値も入れてくれる
image.png

form_withヘルパーとしての主な機能はこれ=裏でhtml記述を自動生成してくれている だけ。

form_withヘルパーの使い方

どの記述で何をしているのか。

本体

<%= form_with(model: @user) do |f| %>
  • "model"オプション

    • フォームを表示する画面に渡ってきたインスタンスを受け取る。ここではuserインスタンス
    • 編集画面で登録済みユーザーの情報をデフォルト値として入れておける
      • ログイン後に訪れる編集画面(/users/:id/edit)ではuserインスタンスが渡ってくる
        • →渡ってきたインスタンスを使ってデフォルト値埋め
      • 新規登録画面(/users/new)では、インスタンスは渡ってこないので@userはnil
  • do {form}

    • ブロック。この記述により、ブロック内でform.xxxの形で便利な各種メソッドを呼び出せる(form_withヘルパーの理解にあたっては、ブロックを必ずしもちゃんと理解している必要はない)

label

<%= f.label :name %>
  • ここを生成する
    image.png
  • "Name"でなく"名前"にしたいなど、表示を変更したいときは
    <%= f.label :name, "名前" %>
    のようにカンマ+文字列で指定してあげれば変更できる
    image.png

input定義

<%= form.text_field :name, class: 'form-control' %>
  • form.text_field
    • フォーム要素の種別を指定できる
      • text_field:1行のテキストボックス
      • email_field:メールアドレス
      • password_field:パスワード
      • etc...もちろんラジオボタンやチェックボックスなども設定可能
  • :name
    • フォームの送信先となるcontrollerのcreate/updateメソッドの引数名↓、及びモデルのパラメータ名(DBのカラム名)と一致させる
    • これにより以下が実現できる
      • フォームの送信をcontrollerで受け取り、DBを更新する
      • DBのデータでフォーム要素をデフォルト値埋めする(編集画面のみ)
users_controller.rb
def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation)
end

フォーム送信先は自動で選択
フォームがsubmitされたとき、controllerのcreateメソッドへのPOSTリクエストか、updateメソッドへのPATCHリクエスト、適切な方を自動で選択してくれます。

form_withヘルパーの仕組み

html要素の自動生成
例えば、ここの記述で

<%= form_with(model: @user) do |form| %>
 <%= form.label :name %>
 <%= form.text_field :name, class: 'form-control' %>
~~~

このようなHTMLが生成される

<label for="user_name">Name</label>
<input class="form-control" type="text" value="Example User" name="user[name]" id="user_name">

これを見ると、

  • form.label によりlabel要素が、
  • form.text_fieldによりinput要素(type="text") が生成されていること

がわかる。さらに、

  • form_with(model: *@xxx*)で指定した値が、label要素のfor属性、input要素のname/id属性に反映されていること
  • form.label :*xxx*がfor属性に反映されていること
  • form.text_field :*xxx*がname/id属性に反映されていること

もわかる。
なので例えば、下記のように書き換えをすると

<%= form_with(model: @user) do |form| %>
 <%= form.label :name %>
 <%= form.text_field :★適当な名前★, class: 'form-control' %>

生成されるhtmlもそれに合わせて変わることになる。

<label for="user_name">Name</label>
<input class="form-control" type="text" name="user[★適当な名前★]" id="user_★適当な名前★">

指定する値の名前をcontrollerの引数(DBのカラム名)に合わせる必要があるのは、ここの名前がそのままname属性に渡ってしまうからということですね。

フォーム送信先の自動選択
modelにインスタンスが渡ってきているかで判断してくれる。

  • 新規登録画面=modelオプションにインスタンスが渡ってきていない場合はcontroller#createへPOSTリクエスト
  • 編集画面=modelオプションにインスタンスが渡ってきている場合はcontroller#updateへPATCHリクエスト
    という形で送り分けてくれる。
<form action="/users" accept-charset="UTF-8" method="post">

ユーザー編集画面のフォーム

<form action="/users/1" accept-charset="UTF-8" method="post">
<input type="hidden" name="_method" value="patch" autocomplete="off">

※ HTMLのform要素はGETとPOSTにしか対応していないため、PATCHリクエストするには工夫が必要。railsはname=_methodを用いてサーバ側にリクエストするメソッドを設定可能

何が嬉しいのか

所感に近いですが、上記をふまえて以下あたりはありがたいなと思いました。

  • 命名規則に従っていればフォーム送信、デフォルト値埋めが何も考えずともできる(これがメイン)
  • 各フォーム要素、種別が違ってもほぼ同じ書き方ができるので可読性が上がる
  • 記述量が減るのでタイポが減る

その他

model以外にも様々なオプションがある。
https://railsdoc.com/page/form_with
一部抜粋

オプション 効果
scope scope: session modelを指定しない場合には指定の必要あり。
controller#createにデータを読み取ってもらうのに使う(name属性のプレフィックスになる)。
例の場合だと、controller側にてsession.xxxでパラメータを読み取れる
url url: login_path modelを指定しない場合に指定の必要あり。
サブミット先のパスを指定する。
modelを指定している場合は(命名規則に基づき)、該当のモデルの/newないし/editのパスを自動で設定してくれている。
method mthod: post サブミット時のHTTPメソッドを指定する。
普通のmvcの場合はviewがnewかeditかでpostかputか汲み取ってくれるので不要

参考

モデルなどからフォームタグを生成 - Railsドキュメント
Railsでform_withでログインする
form_withのlocal: trueって必要なん?これ何なん?(Ruby on Rails)

さいごに

間違いやより正しい表現等を見つけていただけましたら、ご指摘いただけるとありがたいですmm

1
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
1
0