📚

Rails form_withヘルパー

2023/03/26に公開

form_withヘルパーとは

Railsには、Viewなどから呼び出す共通処理をまとめた「ヘルパーメソッド」が用意されている!

form_withヘルパーもその1つで
セキュリティ対策などが組み込まれた安全なHTMLのformタグを作成でき、
Railsの機能を最大限生かすことが可能 🙆🏻‍♀️

form_withの基本形

<%= form_with do |f| %>
<% end %>

「|f|」の部分はブロック変数と言い、特定の範囲内で使える変数のことで、
今回だとform_withと同じdoからendまでの範囲で使うことができる変数のこと。

この基本形から、モデルとの連携・どのURLへデータを送るのか・どのHTTPメソッドで送るのかなどを定義し、実際に作るアプリケーションの要件に合わせてフォームの作成を行う!

フォームの要素を作成する

フォームからデータを送信した後にデータベースへ保存する必要がある場合
モデルと連携を行う必要があり、その情報を含めるとform_withは次のようになる!

基本形からListモデルと連携したform_with

<%= form_with model: List.new do |f| %>
<% end %>

「List.new」とは?

「List.new」と定義することで、Listモデルの情報をもとに
新しくオブジェクトが作成され、Listモデルに存在するtitle・bodyが格納できるようになる。

form_withはこのようにモデルと連携することで、データを簡単に保存ができたり
後の章で紹介するバリデーションなどを簡単に設定することができる!!

modelオプションでList.newを設定するだけで、
自動的CreateアクションのURLへ送信することができるということになる。

フォームに部品を追加する

form_withの範囲の中に、テキストフィールドや送信ボタンなどの部品を追加していく!

使用場面 SampleAppでの使用箇所 モデルオブジェクト
単一行のテキストフィールド タイトル text_field
複数行のテキストフィールド 本文 text_area
送信ボタン 「投稿」ボタン submit

これらのモデルオブジェクトを作成するために、form_withヘルパーの部分で紹介したブロック変数「f」を使用する。

<h1>新規投稿</h1>
<!-- form_with部分 -->
<%= form_with model: List.new do |f| %>
  <h4>タイトル</h4>
  <%= f.text_field :title %>
	
  <h4>本文</h4>
  <%= f.text_area :body %>
	
  <%= f.submit '投稿' %>
<% end %>

このブロック変数「f」には設定したmodelの情報(今回であればList.new)も含まれているため
後で行う保存機能を追加する際にも簡単且つ安全にデータベースに保存することができる!

コントローラーに記述を追加する

ここまでViewファイルのform_withに直接List.newとモデルの情報を渡していたが、
通常このような記述は行わず、
基本的にモデルなどの処理はViewではなくコントローラーに記述する必要があるため、
インスタンス変数という機能を用いてコントローラーで記述した値をViewで呼び出せるようにする!

インスタンス変数とは

コントローラーアクションとViewファイルでデータの受け渡しができる変数のこと。
@helloのように変数名の先頭に「@(アットマーク)」を付けることでインスタンス変数となる!

コントローラー・アクション

def new
  @hello = "Hello"
end

インスタンス変数を定義
👇
viewファイル

<%= @hello %>

ブラウザに Helloと出力される

ローカル変数とは

ローカル変数とは、インスタンス変数の逆でコントローラーとViewファイルでデータの受け渡しができない変数のこと。
インスタンス変数とは違い、変数名の先頭に何も付けない場合はローカル変数となる!

コントローラー・アクション

def new
  hello = "Hello"
end

インスタンス変数を定義
👇
viewファイル

<%= hello %>

表示することができず、エラーが発生する!

まとめ

インスタンス変数

  • 変数の名前の先頭に@マークをつける
  • コントローラーとViewでデータの受け渡しができる

ローカル変数

  • 変数の名前の先頭には何もつけない
  • コントローラーとViewでデータの受け渡しができない

newアクションに記述を追加する

form_withに記述していたList.newをインスタンス変数を用いて
コントローラーのnewアクションに定義しViewの記述の書き換えを行う。

インスタンス変数@listを定義し、List.newを格納する!

class ListsController < ApplicationController
  def new
    # Viewへ渡すためのインスタンス変数に空のModelオブジェクトを生成する。
    @list = List.new  
  end
end

Viewファイル(new.html.erb)の記述も変更する!

<h1>新規投稿</h1>
<%= form_with model: @list do |f| %>
  <h4>タイトル</h4>
  <%= f.text_field :title %>
	
  <h4>本文</h4>
  <%= f.text_area :body %>
	
  <%= f.submit '投稿' %>
<% end %>

form_withについての補足

作成したform_withには、List.newとモデルと連携させることにより、送信先のURLを判別するものだったが、慣れる前からこの省略形で扱うと、意図しない問題の原因にもなるので、厳格な書き方にまずは慣れるようにする!

厳密な記述への修正を行うため、Viewファイルの編集をする。
使用する2つのオプション

  • url
    どのURLへフォームの情報を送信するか
  • method
    HTTPメソッドを指定
<h1>新規投稿</h1>
<!-- form_withにオプション追記 -->
<%= form_with model: @list, url: '/lists', method: :post do |f| %>

  <h4>タイトル</h4>
  <%= f.text_field :title %>
  
  <h4>本文</h4>
  <%= f.text_area :body %>
  
  <%= f.submit '投稿' %>
  
<% end %>

form_withについて注意

tableタグの中でform_withを使う場合の注意点
書く位置によってはformタグがうまく生成できずフォームがうまく機能しないことがある。

1. tableタグ直下にform_withを使っている
2. trタグ直下にform_withを使っている

formタグが子要素を持たないまま生成されてしまうので
使い方に気を付ける!


課題やりながらインスタンス変数等`が理解できてなかったから復習!
色々とファイルが多くて呼び出したりするのが複雑でここらへんちゃんと理解していないとだめだ〜〜
でも少しずつわかってきてる感じがして楽しい!
頑張ろう!

Discussion