LoginSignup
0
1

More than 1 year has passed since last update.

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

Last updated at Posted at 2021-10-07

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

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

<%= 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を生成してくれます。

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

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

<%= form_with(model: @user, local: true) do |f| %>

model @userの部分はviewを呼び出したコントローラー側で、作成したインスタンスです。

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

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

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

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

<form accept-charset="UTF-8" action="/users" method="post">

↓id:1のユーザー情報を編集する時は、このように生成してくれます。

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

httpリクエストでPATCHリクエストは存在しないので、 inputタグで偽造します、
これも自動生成されます。

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

<%= f.label :name %>
<%= f.text_field :name %>
<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も同じ様な感じで生成されます。

<%= f.label :email %>
<%= f.email_field :email %>
<label for="user_email">Email</label>
<input id="user_email" name="user[email]" type="email" />

<%= f.label :password %>
<%= f.password_field :password %>
<label for="user_password">Password</label>
<input id="user_password" name="user[password]" type="password" />

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

<%= 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が生成される。

<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」」のようになりモデルを渡した時と同じ実装ができます。
↓試しにスコープを追加してみます。

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

↓先ほどのモデルを渡した時と同じような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が自動で振り分けてくれますが、ルーティングがうまく動かない時は、直接コントローラー名やアクション名を指定できます。

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

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

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

コントローラー
def new
  @user = User.new
  #新しいuserインスタンスを作成
end
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でモデルを作成することもできます。

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/

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