form_withと仲良くなろう

form_withってよく使うけど曖昧なままきてるなあ、と思ったので振り返ってみます。以前にも一度記事にしたので2回目です。
色々やってくれる優秀なform_withですが、model渡したりurl渡したり、結局どんな動きしてるの?

form_withとは

情報を送信するためのヘルパーメソッドです。

urlを渡す

urlはフォームの情報の送信先のURLを指定するためのオプションです。
urlを渡すと、そのpathに対してデフォルトではPOSTメソッドでリクエストが送られます。

<!-- ログインフォーム -->

<%= form_with url: login_path, local: true do |f| %>
  <%= f.label :email %>
  <%= f.text_field :email, class: 'form-control' %>

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

  <%= f.submit  class: 'btn btn-primary' %>
<% end %>

ログインの情報はユーザー照合するだけでDBに保存しないのでmodelは渡しません。(と思ってるのですが自信ないので間違ってたらご指摘ください。)

modelを渡す

modelはDBに保存する時に指定します。

<!-- ユーザー登録、更新フォーム -->

<%= form_with model: @user, local: true do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name, class: 'form-control' %>

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

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

  <%= f.label :password_confirmation %>
  <%= f.password_field :password_confirmation, class: 'form-control' %>
        
  <%= f.submit  class: 'btn btn-primary' %>
<% end %>

modelに指定している@userはコントローラで定義したインスタンスです。
このインスタンス
値が入ってるか
で処理が変わります。

空の場合は

def new
  @user = User.new. # 空のインスタンスを作成
end

def create
  @user.create(user_params)
end

private

def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation)
end

空ってことは新規作成したいんだな
 ↓
createアクション

値が既に入ってる場合は

def edit
  @user = User.find(params[:id]) # ユーザー情報をfindで取得して@userに代入
end

def update
  @user.update(user_params)
end

private

def user_params
  params.require(:user).permit(:name, :email, :password, :password_confirmation)
end

値が既に入ってるから更新したいんだな
 ↓
updateアクション

という感じで判断してくれます。

最後に

form_with然り、render然り、redirect_to然り、Railsはその「よしなに力」の高さ故、初学者にとっては逆に何をやってるのかわからない、となりがちだと思います。
なんか動いてるラッキー、ではなく何が省略されてるのか、どんな処理が走っているのか、しっかり理解しながら進めていきたいですね。