【form_with】基本的な書き方・複数のモデルを引数に指定(ネスト)する書き方
この記事の対象者
- 基本的なform_withの書き方(旧form_tag, 旧form_for)を知りたい方
- ルーティングがネストしている場合に、複数のモデルを引数に指定する書き方を知りたい方
目次
form_withとは
Rails5.1から追加されたフォーム作成を行うためのヘルパーメソッドのことです。
それ以前では、データの保存を伴わない場合はform_tag、
データの保存を伴う場合はform_forを使用していました。
Rails5.1以降では、
データの保存を伴わない場合も、データの保存を伴う場合もform_with1つで実装出来るようになりました。
そのため、form_withの書き方には、
- データの保存を伴わない書き方(旧form_tag)
- データの保存を伴う書き方(旧form_for)
の2種類があります。
また、データの保存を伴う書き方には、
- 引数に1つのモデルを指定する方法
- 引数に複数のモデルを指定する方法
があります。
データの保存を伴わない場合の書き方(旧form_tag)
基本的な書き方はこんな感じです。
<%= form_with url: "パス" do |form| %> フォームの内容 <% end %>
例えばposts_pathに対して「title」の情報を送信したい場合、このように書きます。
<%= form_with url: posts_path do |form| %> <%= form.text_field :title %> <%= form.submit %> <% end %>
これでurl(posts_path)に対して、text_fieldに入力された「title」の情報を渡すことが出来ます。
データの保存を伴う書き方(旧form_for) 引数に1つのモデルを指定
基本的な書き方はこんな感じです。
<% form_with model: モデルクラスのインスタンス do |f| %> フォームの内容 <% end %>
例えばpostモデルのインスタンスを保存・更新させるフォームを書く場合、このように書きます。
<%= form_with model: @post do |f| %> <%= f.label :title, "タイトル" %> <%= f.text_field :title %> <%= f.label :body, "本文" %> <%= f.text_area :body %> <%= f.submit "送信" %> <% end %>
1行目には、postコントローラのnewアクション又はeditアクションで定義したインスタンス(@post)が引数として渡されています。
def new @post = Post.new end def edit @post = Post.find(params[:id]) end
@postの中身が空(new)の場合はcreateアクションが呼ばれ、
中身が入っている場合(edit)の場合はupdateアクションが呼び出されます。
form_withではこのように自動的にインスタンスの中身を判断して、次に行うアクションを決定してくれます。
データの保存を伴う書き方(旧form_for) 引数に複数のモデルを指定
下記のようにルーティングでネストをしている場合に、
resources :posts do resources :comments, only: [:edit, :update, :create, :destroy] end
commentモデルクラスのインスタンスを保存・更新したい場合、
form_withに2つの引数を指定する必要があります。
<%= form_with model: [@post, @comment] do |f| %> <%= f.text_area :body, placeholder: "コメントする" %> <%= f.submit "SEND" %> <% end %>
ルーティングのネストについては、こちらの記事で解説しています♪
2つの引数を渡したい場合、アクションにも2つのインスタンスを定義します。
def show @post = Post.find(params[:id]) @comment = Comment.new end
def edit @post = Post.find(params[:post_id]) @comment = Comment.find(params[:id]) end
複数のモデルクラスインスタンスを渡す場合、
2つ目の引数(@comment)の中身が空のときはcreateアクションが実行され、
中身が入っているときはupdateアクションが実行されます。
まとめ
- form_withとはRails5.1から使用出来るようになったヘルパーメソッドで、以前はform_forとform_tagが使われていた
- ルーティングをネストしている場合は、引数に指定するモデルを複数指定する必要がある
参考記事