Form_withヘルパー【虎の巻】

### 【概要】
---
Railsでフォームを作成する際には、form_withヘルパーが必須知識となります。ぜひマスターして使いこなせるようになりましょう！
またセットでrenderを使用することがありますが、そちらの詳細については別紙で解説しております。

### 環境
---
この記事は下記の実行環境で動作確認しております。
・Rails 7.0.4 
・Ruby 3.1.4

Rails5.1以前のバージョンについては割愛しますので、そちらをご使用の方は下記記事をご参照ください。

【Rails】form_forの基本の基

https://qiita.com/manbolila/items/b8336ab115f3aebacbb9


### Form_withヘルパーとは
---
まずは、Form_withヘルパーについて整理しておきましょう。
Form_withヘルパーとは下記のような機能を実装する手助けとなるものです。

### ・Viewファイル内で簡潔にフォームを生成することができるヘルパーを生成できます。
### ・入力値の送信先も設定できる為、コントローラへのデータ引き継ぎもスムーズに行うことができます。

From_withヘルパーを使用することで、上記のような恩恵を受け取ることができます！
(HTMLでのデータのやり取りをRailsでもできると考えてくれるとわかりやすいと思います。)

### Form_withの基本的な使用方法
---
Form_withヘルパーがどのようなものか理解していただいたかと思います。

では実際にはどのように使用すればいいのでしょうか？
下記にサンプルを示しますので、MVCモデルから少しずつ紐解いていきましょう！

◇Model◇
```ruby
<!-- db/schema.rb -->
ActiveRecord::Schema[7.0].define(version: 2022_07_27_061048) do
  create_table "users", charset: "utf8mb4", force: :cascade do |t|
    t.string "email", null: false
    t.string "crypted_password"
    t.string "salt"
    t.string "first_name", null: false
    t.string "last_name", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
  end
```

◇Controller◇
```ruby
<!-- app/controllers/users_controller.rb -->
  def create #ストロングパラメータから、値を取得
    @user = User.new(user_params)
    if @user.save
    ~

private
#private配下に取得したいスロトングパラメータを設定(ストロングパラメータについては、説明を割愛します。)
  def user_params
    params.require(:user).permit(:first_name, :last_name, :email, :password, :password_confirmation)
  end
end
```
◇View◇
```ruby
<!-- app/views/users/new.html.erb -->
<div class="container">
    #以下、form_withヘルパーの実装になります。
      <%= form_with model: @user do |f| %>
        <div class="mb-3">
          <%= f.label :last_name, class: "form-label" %>
          <%= f.text_field :last_name, class: "form-control" %>
        </div>
        <div class="mb-3">
          <%= f.label :first_name, class: "form-label" %>
          <%= f.text_field :first_name, class: "form-control" %>
        </div>
        <div class="mb-3">
          <%= f.label :email, class: "form-label" %>
          <%= f.email_field :email, class: "form-control" %>
        </div>
        <div class="mb-3">
          <%= f.label :password, class: "form-label" %>
          <%= f.password_field :password, class: "form-control" %>
        </div>
        <div class="mb-3">
          <%= f.label :password_confirmation, class: "form-label" %>
          <%= f.password_field :password_confirmation, class: "form-control" %>
        </div>
        <%= f.submit "登録", class: "btn btn-primary" %>
      <% end %>
```

◇yml◇ ※i18n使用の場合
```ruby
<!-- config/locales/activerecord/ja.yml -->
ja:
  activerecord:
    models:
      user: ユーザー
    attributes:
      user: #i18nを使用している場合は、labelから名称を取得できます。
        email: メールアドレス
        last_name: 姓
        first_name: 名
        password: パスワード
        password_confirmation: パスワード確認
```
上記が実装のサンプルです！
ここまでの流れを整理すると、1〜3までの流れになります。

1.Modelの定義
2.Controllerで`ストロングパラメータ`及び、`パラメータを取得するアクション`を定義
3.対応するViewで`form_withヘルパー`を使用

ここからはform_withヘルパーを掘り下げていきましょう!

### 基本構文
---
```ruby
<%= form_with(モデル or スコープ or URL [,オプション]) do |f| %>
```

### 使用できるオプションの種類
---
※railsでは下記のlocal以降の項目に関して、自動で設定しているので初心者の方は上記3つを覚えてください！
(ただし、明示した方がコードリーディングする側にとって親切です。)
|オプション|説明|設定項目(例)|
|:-:|:-:|:-:|
|:model|モデル指定|@postなど|
|:url|URL指定|boards_pathなど|
|:local|リモート送信の無効||
|:remote|リモート送信|true|
|:method|HTTPメソッドの指定|post(ただし、Rails のフォームヘルパーは、適切な HTTP メソッドを自動的に選択)|
|:id|id属性を指定||
|:class|class属性を指定|

>> @yamaday0uさん　Rails：form_withのオプションや特徴について整理より引用。

【基本構文】と【オプション】から実装したい機能に合わせて、適切なフォームを組み立てましょう!
それぞれ簡単なサンプルを載せますので、ご参考にしてください。

### モデルの場合
---
・フォームに対するモデルが1件の場合
```ruby
<!-- app/views/posts/edit.html.erb -->
<%= form_with(model: @post) do |f| %>
  <!-- フォームの内容 -->
<% end %>
```
・フォームに対するモデルがN件の場合
```ruby
<!-- app/views/posts/edit.html.erb -->
<%= form_with(model: [@post, @comment]) do |f| %>
  <!-- ポストフォームの内容 -->
  <%= render 'comments/form', comment: @comment %>
<% end %>
```
---

### スコープの場合
---
※scopeは一般的にはあまり使用しないので、さっと見をお勧めします。
```ruby
<!-- app/views/posts/new.html.erb -->
<%= form_with(scope: :new) do |f| %>
  <!-- フォームの内容 -->
<% end %>
```
または
```ruby
<!-- app/views/posts/new.html.erb -->
<%= form_with(scope: '/custom_url') do |f| %>
  <!-- フォームの内容 -->
<% end %>
```
---

### URLの場合
---
```ruby
<!-- app/views/posts/edit.html.erb -->
<%= form_with(url: edit_post_path(@post)) do |f| %>
  <!-- フォームの内容 -->
<% end %>
```

```ruby
<!-- app/views/posts/show.html.erb -->
<%= form_with(url: post_comments_path(@post)) do |f| %>
  <!-- コメントフォームの内容 -->
<% end %>
```

### モデル,URLがMIXパターン
---
```ruby
<!-- app/views/comments/_form.html.erb -->
~
<%= form_with model: comment, url: board_comments_path(@board) do |f| %>
#モデル ->コメントモデルに値を設定
#URL ->コメント#アクションに対応するアクションがないために明示
```
ここで、モデルとURLの使い分けのみ解説します。
基本的には form_with のオプションでは model: を使用すると覚えて構いません。

### ただし、次のような場合に限り、 url: オプションを使います。このポイントは抑えましょう。
・モデルとフォームが紐づかない場合（例: ログインフォーム: user_sessions）
・createやupdateを行うコントローラがモデルと単純に紐づかない場合
（例: model: @user と設定したが、 members_controller に処理が遷移して欲しい場合）

また、modelの場合は、インスタンス変数に値が残りレンダリングすれば入力値を再度表示できますが、URLの場合は、インスタンス変数で値を持っていない為、注意しましょう!!



### フォーム要素を作成するヘルパー
---
フォームでは、上記の`label`や`text_field`以外にも使用できるオプションがあります。
用途によって、下記から選んで使用しましょう！

|メソッド名|機能の説明|メソッド名|機能の説明|
|:-:|:-:|:-:|:-:|
|label|検索用ボックス|week_field|週ボックス|
|search_field|ラベルを作成|telephone_field|電話番号用ボックス|
|text_field|テキストボックス|file_field|ファイル選択用ボックス|
|email_field|メールアドレス用ボックス|password_field|パスワード用ボックス|
|range_field|範囲選択バー|hidden_field|隠しフィールド|
|number_field|数値選択|text_area|テキストエリア|
|select|選択ボックス|check_box|チェックボックス|
|date_field|日付ボックス|radio_button|ラジオボタン|
|datetime_field|日付時刻ボックス|url_field|URLボックス|
|datetime_local_field|日付時刻ボックス|color_field|色選択ボックス|
|month_field|月ボックス|submit|提出用ボタン|
|time_field|時刻ボックス|

>> @Hal_maiさん　【Rails】フォームヘルパーの種類と例より引用。

### 追記
---
再利用性高いパーシャルなどは、ローカル変数で値を管理することが多いので、`render`と`パーシャルファイル`を適切に設定してあげましょう！
valueでインスタンス変数を設定してあげれば問題ないです!

```ruby
#renderを下記のように指定
<!-- comment/new/html.erb -->
~
<%= render 'comments/comment', comment: @comment %>
#renderがローカル変数の場合
```

```ruby
<!-- _comment.html.erb -->
<% if comment.new_record? %>
    <%= form_with(model: comment) do |f| %> 
#ローカル変数で管理する場合は、上記のようにしてください。
```
### 【引用元】
---
Railsガイド
https://railsguides.jp/form_helpers.html
Rails：form_withのオプションや特徴について整理
https://qiita.com/yamaday0u/items/a3689bc48a7eff55929b
【Rails】フォームヘルパーの種類と例
https://qiita.com/Hal_mai/items/1e5afd0c99dd9059839f
【Qiita】テーブルはショートカットコマンドでサッと書ける。表の挿入とフォーマット調整方法。
https://qiita.com/shizen-shin/items/d5eccb343a1c201e2f83