30代未経験からWebエンジニアになった私のプログラミング学習日記

【form_with】基本的な書き方・複数のモデルを引数に指定(ネスト)する書き方

2022/12/31
 
この記事を書いている人 - WRITER -

 

この記事の対象者

  • 基本的な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 %>

 

ルーティングのネストについては、こちらの記事で解説しています♪

【Rails】基本的なルーティングの書き方、ネスト・resourcesについても解説

 

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が使われていた
  • ルーティングをネストしている場合は、引数に指定するモデルを複数指定する必要がある

 

参考記事

 

 

この記事を書いている人 - WRITER -

- Comments -

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


Copyright© 30代未経験からのプログラミング , 2022 All Rights Reserved.