Railsのform_withの使い方を素人ながらまとめました。

##form_withはフォームにす関するHTML要素を簡単に生成することができる便利なメソッド

まずフォームの値をデータベースに保存する際の書き方です。
↓railsでこう書くと

```java
<%= form_with(model: @user, local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
```
↓HTMLを生成してくれます。

```html
<form accept-charset="UTF-8" action="/users" method="post">
  <label for="user_name">Name</label>
  <input id="user_name" name="user[name]" type="text" />

  <label for="user_email">Email</label>
  <input id="user_email" name="user[email]" type="email" />

  <label for="user_password">Password</label>
  <input id="user_password" name="user[password]"
         type="password" />

  <label for="user_password_confirmation">Confirmation</label>
  <input id="user_password_confirmation"
         name="user[password_confirmation]" type="password" />

  <input class="btn btn-primary" name="commit" type="submit"
         value="Create my account" />
</form>
```

では、内部構造を見ていきます。

```java
<%= form_with(model: @user, local: true) do |f| %>
```
model @userの部分はviewを呼び出したコントローラー側で、作成したインスタンスです。

```java:コントローラー
def new
  @user = User.new
  #新しいuserインスタンスを作成。
end
```
つまり「model: @user」の@userは**空のインスタンス**です。
railsは空のインスタンスをmodelに渡すと、**「フォームの内容で新しくユーザーを作成したいだろうからcreateアクションにPOSTリクエスト投げるね」**と勝手に解釈してくれます。

逆に言うと@userにデータがある場合は**「ユーザー情報の更新がしたいんだね」**と解釈してupdateアクションにPATCHリクエストをなげてくれます。

↓createアクションにPOSTリクエストを投げる時は、このように作成してくれます。

```html
<form accept-charset="UTF-8" action="/users" method="post">
```
↓id:1のユーザー情報を編集する時は、このように生成してくれます。

```html
<form accept-charset="UTF-8" action="/users/1" method="post">
<input type="hidden" name="_method" value="patch">
```
httpリクエストでPATCHリクエストは存在しないので、 inputタグで偽造します、
これも自動生成されます。

ブロック引数のfは、HTML要素を生成するメソッドを持っています。
引数は**「:カラム名」**とします。

```java
<%= f.label :name %>
<%= f.text_field :name %>
```

```html
<label for="user_name">Name</label>
<input id="user_name" name="user[name]" type="text" />
```
勝手にfor,id,name,type名を設定してくれます。
name属性が「user[name]」となっているので、コントローラーで値を受け取る場合は、「params[:user][:name]」とすると取得できます。

email,passwordも同じ様な感じで生成されます。

<email>

```java
<%= f.label :email %>
<%= f.email_field :email %>
```

```html
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="email" />
```
<password>

```java
<%= f.label :password %>
<%= f.password_field :password %>
```

```html
<label for="user_password">Password</label>
<input id="user_password" name="user[password]"　type="password" />
```

##モデルのインスタンスを渡さないでパスを書くこともできます。

```java
<%= form_with(url: "/users", local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
```
↓このようなHTMLが生成される。

```html
<form accept-charset="UTF-8" action="/users" method="post">
  <label for="name">Name</label>
  <input id="name" name="name" type="text" />

  <label for="email">Email</label>
  <input id="email" name="email" type="email" />

  <label for="password">Password</label>
  <input id="upassword" name="password"
         type="password" />

  <label for="password_confirmation">Confirmation</label>
  <input id="password_confirmation"
         name="password_confirmation" type="password" />

  <input class="btn btn-primary" name="commit" type="submit"
         value="Create my account" />
</form>
```

url指定、user[name]みたいなname属性にはなりません。
ただしform_withの引数に**「scope: :スコープ名」**を追加するとname属性は**「スコープ名「name」」**のようになりモデルを渡した時と同じ実装ができます。
↓試しにスコープを追加してみます。

```java
<%= form_with(url: "/users",scope: :user, local: true) do |f| %>
```

↓先ほどのモデルを渡した時と同じようなHTMLが作成されました。

```html
<form accept-charset="UTF-8" action="/users" method="post">
  <label for="user_name">Name</label>
  <input id="user_name" name="user[name]" type="text" />

  <label for="user_email">Email</label>
  <input id="user_email" name="user[email]" type="email" />

  <label for="user_password">Password</label>
  <input id="user_password" name="user[password]"
         type="password" />

  <label for="user_password_confirmation">Confirmation</label>
  <input id="user_password_confirmation"
         name="user[password_confirmation]" type="password" />

  <input class="btn btn-primary" name="commit" type="submit"
         value="Create my account" />
</form>
```

##コントローラー名やアクション名を指定することもできます。
基本はモデルを渡せばrailsが自動で振り分けてくれますが、ルーティングがうまく動かない時は、直接コントローラー名やアクション名を指定できます。

```java
<%= form_with @user, url: {controller: 'users', action: 'index' } do  |f| %>
  <%= f.text_field :name %>
  <%= f.submit %>
<% end %>
```

##view側でformに渡すモデルを作成しても動きます。

先ほどはコントローラーでモデルを作成し、viewに渡していました。

```java:コントローラー
def new
  @user = User.new
  #新しいuserインスタンスを作成。
end
```

```java:view
<%= form_with(model: @user, local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
```

ですがモデルはコントローラーで作成しなければいけないわけではないので、以下のようにviewでモデルを作成することもできます。

```java:view
<%= form_with(model: User.new, local: true) do |f| %>
      <%= f.label :name %>
      <%= f.text_field :name %>

      <%= f.label :email %>
      <%= f.email_field :email %>

      <%= f.label :password %>
      <%= f.password_field :password %>

      <%= f.label :password_confirmation, "Confirmation" %>
      <%= f.password_field :password_confirmation %>

      <%= f.submit "Create my account", class: "btn btn-primary" %>
    <% end %>
```

#参考

>https://pikawaka.com/rails/form_with
>https://railstutorial.jp/