【Rails入門説明書】form_withについて解説

公開日: 2018.10.31
更新日: 2024.01.12
Railsのdeviseを用いてログイン認証を実装する方法を解説

はじめに

Rails5.1で導入されたform_withヘルパーは、非推奨(将来的になくなる)になったform_forヘルパーとform_tagヘルパーの代わりとなるヘルパーです。

つまり、form_withヘルパーは、form_forヘルパーと同等の動きをするヘルパーと言えます。

ただし、当然ながら改善点もありますし、form_tagヘルパーとも統合されていますので、機能的には拡張されていると言えます。

そもそも、form_forヘルパーはよく使うヘルパーの1つでしたので、form_withヘルパーも同様によく使うことになります。

今回は、form_withヘルパーについては、form_forヘルパーと比較することで詳しく解説しますので、是非お役立てください。

なお、form_forヘルパーについては、「【Rails入門説明書】form_forについて解説」で詳しく解説しています。まだお読みでない場合は、先にお読みいただくことをおすすめします。

冒頭で記載しているように、form_withヘルパーは、Railsのバージョンが5.1以降でなければ使用できません。コマンドプロンプトで以下のコマンドを実行し、表示されるRailsのバージョンが5.1未満の場合は、5.1以上のバージョンをインストールしてください。
[bash]
rails -v
[/bash]

form_withヘルパーを読み解く

form_withヘルパーは、Viewファイルで使用することで、簡単にフォームを生成することができるヘルパーです。同時に、入力値の送信先もシンプルに設定でき、コントローラへのデータ引き継ぎもスムーズに行うことができます。

そんなform_withについて、まずはその動きを追って確認してみましょう。

環境設定

プログラムコードやHTMLを確認しますので、まずはテスト環境を設定します。

コマンドプロンプトを起動して、以下のコマンドを実行してください。
※詳細は、「【Rails入門説明書】scaffoldについて解説」を確認してください。

[bash]
$rails new formw_test
$cd formw_test
$rails generate scaffold User name:string age:integer email:string password:string note:text
$rails generate scaffold Item title:string price:integer user_id:integer
$rake db:migrate
$rails c
$User.create(name:”Arioka”, age:30, email:”dai@hese.jp”, password:”0000″, note:”member”)
$User.create(name:”Yamada”, age:28, email:”ryo@hese.jp”, password:”1111″, note:”top”)
$Item.create(title:”ring”, price:50000, user_id:2)
$Item.create(title:”necklace”, price:20000, user_id:2)
$Item.create(title:”computer”, price:200000, user_id:1)
$exit
[/bash]

モデルファイルを修正し、2つのモデルの関連付けを行います。
(app/models/user.rb)

class User < ApplicationRecord
has_many :items
end

(app/models/item.rb)

class Item < ApplicationRecord
belongs_to :user
end

サーバーを起動し、ブラウザで「localhost:3000/users」「localhost:3000/items」にアクセスすると、以下のように表示されます。

form_withヘルパーの確認

では、フォームを表示するためのViewファイルapp/views/users/_form.html.erbを確認していきましょう。1行目にform_withが使用されています。
(app/views/users/_form.html.erb)


<%= form_with(model: user, local: true) do |form| %>
・・・
<% end %>

form_withヘルパーには、複数のオプションが準備されていますが、scaffoldでは「:model」オプションと「:local」が使われています。

オプション

「:local」オプションは、submitによるデータ送信にAjaxを使わないことを示すオプションです。旧バージョンのform_forヘルパーでは、デフォルトでAjaxを使うことがありませんでしたので、それに合わせて使用しないように設定しています。(このオプションについては、Form_withヘルパーの本質とはずれますので、説明はここまでにします)

「:model」オプションは、生成するフォームがどのモデルに基づいて作られるかを示すオプションです。form_forヘルパーの第1引数と同じですので、このモデルから推測された送信先へ送信するフォームが生成されます。

具体的には、以下のようなフォームが生成されています。

<form action=”/users” method=”post”>
・・・
</form>

※なお、実際には、過去のブラウザ(IE5以前)での文字化け防止のための「accept-charset」属性や非表示(Hidden属性)のUTF-8タグ、CSRF(クロスサイト・スクリプト・フォージェリ)攻撃対策の非表示タグも生成されていますが省略しています

生成されたHTMLでは、HTTPリクエストが「POST」、送信先URLが「/users」に設定されています。

フォームIDとクラス属性

form_withの導入によって、Rails5.1では、フォームID(id)とクラス属性(class)は自動付与されなくなっています。上述しているHTMLにも、「id=」と「class=」が付与されていません。そのため、フォームIDとクラス属性は自分で付与しなければいけなくなりました。
※Rails5.2で自動付与されるように変更されましたので、バージョン5.2以降を使っている人は、自分で付与する必要はありません

その対策の一環として、HTML属性の設定について、form_forヘルパーと設定方法が違っています。

form_forヘルパーでは、HTML属性は、すべて「:html」オプションで設定しなければいけませんでしたが、ID属性とクラス属性、それにdata属性については、その必要はなくなり、それぞれ「:id」オプション、「:class」オプション、「:data」オプションが新設されています。

・form_forヘルパーの場合


<%= form_for(user, html:{class: “new_user”, id: “new_user”, data:{guest: “normal”}}) do |form| %>

・form_withヘルパーの場合


<%= form_with(model: user, local: true, class: “new_user”, id: “new_user”, data:{guest: “normal”}) do |form| %>

どちらでも、以下のHTMLが生成されます。

<form id=”new_user” class=”new_user” data-guest=”normal” action=”/users” method=”post”>

ブロック引数form

form_withヘルパーのブロック引数formは、モデルオブジェクトの情報を保持するFormBuilderオブジェクトであるのは、form_forヘルパーと同じです。

また、フォームコントロールを生成するためのメソッドについても、FormBuilderオブジェクト及び、その親クラスであるHelperを継承しているFormHelperやFormTagHelperのメソッドも使用できます。これも、form_forヘルパーと同じです。

form_withヘルパーとform_forヘルパーの違い

ここまでに確認したものも含めて、form_withヘルパーがform_forヘルパーと違っているところをまとめておきましょう。

モデルを指定するために、「:modelオプション」を利用する
submitによるデータ送信に、デフォルトでAjaxを使う(リモートフォームがオンになっている)
classとidが自動付与されない(Rails5.2以降であれば自動付与される)
「:class」「:id」「:data」の3つのオプションが新設され、これらは「:html」オプションで設定する必要がない
モデルに基づかないフォームを生成できる
テーブルにカラムがないフォームフィールドを扱える

これらの違いを踏まえれば、form_withヘルパーは、今までのform_forヘルパーとまったく同じように扱うことができます。

事実、以下のように変更すれば、何の問題もなく同じ動作をします。(新規作成や編集が何の問題もなく通常通りできます)
(app/views/users/_form.html.erb)
・変更前


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

・変更後


<%= form_for(user) do |form| %>
非公開: 未経験から上京し、エンジニアとしてチームラボグループに転職!【WebCampPro卒業生インタビュー】

この記事を読んでいるあなたへ!

本気でプログラミング学習をするならば、DMM WEBCAMPのSKILLSコースがおすすめです!

ぜひご確認してください。

その他のform_withヘルパーの機能

scaffoldで自動生成されていないため、ここまでに紹介できていない、以下の2つの機能を紹介しましょう。

・モデルに基づかないフォームを生成できる
・テーブルにカラムがないフォームフィールドを扱える

それぞれ、詳しく説明します。

モデルに基づかないフォームの生成

form_withヘルパーにあって、form_forヘルパーにはなかった機能の1つのが、この「モデルに基づかないフォーム」の生成です。

じつは、この機能はform_tagヘルパーというform_forヘルパーと同時に非推奨になったヘルパーの機能で、これらの統合が、form_withヘルパーの大きな目的の1つだったとも言えます。

詳細は後述するとして、「モデルに基づかないフォーム」をテスト環境に追加してみましょう。

form_withヘルパーのオプション指定で:modelオプションを利用しなければ、モデルに基づかないフォームを生成することになります。

しかし、当然ですがモデルからの推測ができませんので、:urlオプションの指定が必要です。しかし、そうなると送信先が固定となりますので、用途は限られてくるでしょう。

例えば、検索フォームなどで利用します。

実際に一覧表示にTitleを検索する検索フォームを追加してみます。なお、新たな動作を追加するためには、View、モデル、コントロールの3つすべてに、追加や変更が必要ですので、憶えておきましょう。

Viewの変更

(app/views/items/index.html.erb)

<%= notice %>

<div id=”input-search”>
<%= form_with(url: items_path, method: :get, local: true) do |f| %>
<%= f.text_field :search %>
<%= f.submit “search” %>
<% end %>
</div>

<h1>Items</h1>

:

まず、一覧表示のViewファイルであるindex.html.erbに、検索フォームを追加します。ここで、:modelオプションの指定をやめて、「モデルに基づかないフォーム」としています。

ただし、その代わりに:urlオプションでデータの送付先(画面遷移先)を指定しています。今回は、一覧画面で表示するリストを検索するフォームですので、検索結果を表示するため、データ送付先は一覧画面(items_path:localhost:3000/items)にしています。

また、HTTPリクエストについても、:methodオプションで「GET」に指定しています。(指定しなければ「POST」になるため)

なお、検索文字列入力用のフォームコントロールは「f.text_field」です。引数の「:search」が、入力された文字列を格納するparamsハッシュのキーです。

モデルの変更

(app/models/item.rb)

class Item < ApplicationRecord
belongs_to :user

# Search method(add search)
def self.search(title)
if title
Item.where([‘title LIKE ?’, “%#{title}%”])
else
Item.all
end
end
end

次に検索処理の本体をモデルファイルに実装します。

今回はitemモデル内を検索しますので、itemモデルのファイルに、検索用のメソッド「search」を追加します。検索する実態はDBであり、モデルは処理だけ提供しますので、クラスメソッドとして実装しています。

引数として、検索フォームに入力された文字列を受け取り、文字列が何かあれば、whereメソッドで検索を行います。(その文字列とItemモデルのtitleカラムと部分一致するものを取得)なければ、今まで通り全データを取得するようにしています。

コントロールの変更

(app/controllers/items_controller.rb)

:
def index
# @items = Item.all
@items = Item.search(params[:search]) # (1)item data from Search View
end
:

コントローラでは、全データ取得の部分を削除して、モデルファイルに追加したsearchメソッドを呼ぶ処理を追加します。このときに渡す引数は、フォームから受け取った値です。

モデルに基づかないフォームの場合、入力されたデータがparamsハッシュに格納されていますので、フォームで指定したキーに基づいて、取得しています。

なお、モデルに基づいたフォームの場合、params[モデル名][キー]になりますので、注意してください。

実行結果

以上の変更を行ったあと、改めて「localhost:3000/items」にアクセスしてみましょう。

先頭に検索フォームが追加されていますので、そこに「r」と入力して検索してみましょう。すると、以下のようにtitleに「r」が含まれているものだけが表示されます。

テーブルにカラムがないフォームフィールド

form_forでは、基づいているモデルのテーブルにカラムがないフォームフィールドは扱えませんでした。

しかし、form_withヘルパーでは、paramsハッシュに問題なく追加され、コントローラへ送られます。

実際に試してみましょう。
(app/views/users/_form.html.erb)


:

<div class=”field”>
<%= form.label :user_id %>
<%= form.number_field :user_id %>
</div>

<!– add(1) –>

<div class=”field”>
<label>Don’t have field</label>
<%= form.text_field :test_string %>
</div>

<!– add(1) –>

<div class=”actions”>
<%= form.submit %>
</div>

<% end %>

「add(1)」に挟まれているテキストフィールドを追加してみてください。

「localhost:3000/items/new」にアクセスしてみると、form_withヘルパーの場合は以下のように正常に動作します。(form_forヘルパーではエラーになってしまいます)

登録しても、「Don’t have field」フィールドに入力した文字列は保存されませんが、コントロールからparams[:item][:test_string]でアクセス可能です。

DMM WEBCAMPの詳細はこちら⇨

“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー

form_withヘルパーの詳細情報

では、ここからは「form_withヘルパー」の構文やオプションなどの詳細を紹介していきましょう。

構文は憶えたほうが良いですが、オプションをすべて憶える必要はありません。わからなくなれば、また本記事を確認していただければ幸いです。

構文

form_with(オプション) do |f|
フォームコントロールの設置
end

オプションには、以下があります。

オプション 説明 デフォルト値
:url フォームに入力されたデータを送信するURL。名前付きルートを直接使用可能 nil
:method HTTPリクエスト(HTTPメソッド)の指定。 POST
:format 送信するデータ形式
JSON形式やXML形式など
:urlオプションが指定された場合は無視される
text/html
:scope ルーティングで名前空間が指定されている場合に利用するプレフィックス指定 nil
:model モデルオブジェクト
オブジェクトが新規レコードの場合は作成フォームが生成され、既存レコードの場合は更新フォームが生成される
nil
:authenticity_token 認証トークンの指定。
カスタム認証トークンでオーバーライドするかfalse、認証トークンフィールドをスキップします。
:local リモートフォームを使わない設定 false
:skip_enforcing_utf8 IE5以前の文字化け対策(UTF-8の矯正送信)のスキップ設定 false
:builder フォームオブジェクトのオーバーライド(オリジナルフォームコントロールの作成) nil
:id オプションのHTML id属性 nil
:class オプションのHTMLクラス属性 nil
:data オプションのHTMLデータ属性 nil
:html id、class、data以外のオプションHTML属性 nil

https://web-camp.io/magazine/archives/12654

まとめ

form_withヘルパーについて、説明しました。form_withヘルパーは、Rails5.1 から導入された新しいヘルパーですので、あまり情報がないかもしれません。しかし、これまで使ってきたform_forヘルパーやform_tagヘルパーの代替えとして、これらの機能を統合して使いやすくしたヘルパーです。今後、新たにRailsアプリケーションの開発を行うときに、知らなければ時代遅れになりますので、今のうちにしっかりと学習しておくことをおすすめします。

・form_withヘルパーは、Rails5.1で導入されたフォームを生成するヘルパー
・form_withヘルパーの導入に伴って、form_forヘルパーとform_tagヘルパーは非推奨になった
・form_withヘルパーは、モデルを指定するために、「:modelオプション」を利用する
・form_withヘルパーは、submitによるデータ送信に、デフォルトでAjaxを使う(リモートフォームがオンになっている)
・form_withヘルパーは、classとidが自動付与されない(Rails5.2以降であれば自動付与される)
・form_withヘルパーでは、モデルに基づかないフォームを生成できる
・form_withヘルパーでは、テーブルにカラムがないフォームフィールドを扱える

【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!

ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。

Rubyの学習がしたい。基礎をしっかりと理解したい

転職のサポートがほしい

と考えている方はぜひお読み下さい。

https://web-camp.io/magazine/archives/8535

また、エンジニア転職は考えていないけれど、プログラミング学習を本気でしたい方はDMM WEBCAMPのSKILLSコースがおすすめです!

無料説明動画が公式ページにありますので、そちらをご覧になってみてください。

関連記事

資料請求

  • 短期集中で最速エンジニア転職を実現-転職成功者インタビュー一覧

    DMM WEBCAMPでは転職成功率98%を実現しています。本資料では、元警察官や元ラーメン屋など様々なバックグラウンドを持つ卒業生の声をお届けします。

    資料をダウンロードする
  • IT技術がもたらす3つの変化と身につけるべきスキル

    IT技術の発展により、今後10~20年程度で47%の仕事がなくなると言われています。どのような変化が訪れ、私達はどのようなスキルを身につけるべきかを解説します。

    資料をダウンロードする
  • 未経験がフリーランスエンジニアになる方法-年収アップで自由な働き方を手に入れる

    働き方改革やリモートワークの影響でフリーランスという働き方の人気は高まりつつあります。フリーランスエンジニアとして活躍するために必要な情報をお届けします。

    資料をダウンロードする

© 2024 WEBCAMP MEDIA Powered by AFFINGER5