Viewフォームヘルパーとは、ControllerやModelではなく、Viewで使うことを想定して、フォームを簡単かつ便利に作るためのヘルパー(道具)のこと。
例えば、content_tagヘルパーというものがあるのだけれど、これはまさにその典型例。
content_tag(:div, "header", class: ["one", "two"])
#=> "< div class="one two" >header< /div >"
という観点からすれば、フォームヘルパーとは、
ということは、ヘルパー全般に言えるけれども、簡単かつ便利になる前の
HTMLタグたちを理解しなければ、フォームヘルパーの意味は理解できないとうこと。
Railsガイドでは、まずform_tag
の説明から始まる。
ここで、form_tag
, form_for
, form_with
の概要を確認する。
form_tag
はモデルに紐づけない場合、form_forはモデルに紐付ける場合に使うform_for
とform_tag
があったform_for
とform_tag
の2つは、form_with
に統合されたということで、まずはform_for
というモデルに紐づけないシンプルなケースを確認しよう。今では、form_with
で書くことが一般的なので、その場合も確認する。
# form_tag
<%= form_tag do %>
Form contents
<% end %>
# form_with
<%= form_with do %>
Form contents
<% end %>
<!-- Railsガイドで紹介されていたHTML -->
<form accept-charset="UTF-8" action="/home/index" method="post">
<div style="margin:0;padding:0">
<input name="utf8" type="hidden" value="✓" />
<input name="authenticity_token" type="hidden" value="f755bb0ed134b76c432144748a6d4b7a7ddf2b71" />
</div>
Form contents
</form>
<!-- Rails 6系で試した場合、すこし違うHTMLが出力された -->
<form action="/" accept-charset="UTF-8" method="post">
<input type="hidden" name="authenticity_token" value="E3gz0DuIaaH2ah/jibBQN5pOw5fRWu/0EKopuZ3uCkpoxldUUdSGWt9fQeYnrtuRu0EwofSmrCSoQ3iSKmuwKQ==">
Form contents
</form>
前回の記事で触れたとおりだが、以下を確認しよう。
なお、前回記事では触れなかったが、下記のとおりである。
そんなに重要ではないと思うけど一応確認する。
デフォルトでは、現在のURLに対してPOSTメソッドでHTTPリクエストが送られる。 なので、送信先のURLやメソッドに関する記述がなくとも、先ほどのようなHTMLタグが生成される。
モデルに紐づかないフォームとしてありがちなのが、検索フォームだ。
この場合、actionやmethodがデフォルトのままだと困るので、設定する必要がある。
また、検索フォームの場合、何のフォームであるか示すため、
左横なんかにラベルがついていることが一般的だと思う。
そして、当然検索ワードを入力するtextなどの入力フォームや送信ボタンが必要となる。
ということで、このような記述になる。
せっかくなので、form_withバージョンで書いてみる。
<%= form_with(url: "/search", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
<form accept-charset="UTF-8" action="/search" method="get">
<div style="margin:0;padding:0;display:inline">
<input name="utf8" type="hidden" value="✓" />
</div>
<label for="q">Search for:</label>
<input id="q" name="q" type="text" />
<input name="commit" type="submit" value="Search" />
</form>
GETメソッドの場合、parameterはURLにくっつけるような形で送信される。
例えば、googleでmiketaと検索すると、以下のようなURLにリダイレクトされる。
[https://www.google.com/search?q=miketa&rlz=1C5CHFA_enJP891JP891&oq=miketa&aqs=chrome..69i57j69i59l2j69i60l4j69i65.551j0j15&sourceid=chrome&ie=UTF-8](https://www.google.com/search?q=miketa&rlz=1C5CHFA_enJP891JP891&oq=miketa&aqs=chrome..69i57j69i59l2j69i60l4j69i65.551j0j15&sourceid=chrome&ie=UTF-8)
不勉強なので詳しいことは分からないが、以下のようなパラメータが送られている。本筋から外れるのでこれ以上は踏み入らないが、各メソッドの違いを意識するとよい。
q: miketa
rlz: 1C5CHFA-en....
aqs: chrome..69i...
sourceid: chrome
ie: UTF-8
Railsガイドには、以下のように書いてある。
form_tagヘルパーは2つの引数を取ります。
1つはアクションへのパスで、もう1つはオプションのハッシュです。このハッシュには、フォーム送信のHTTPメソッドやHTMLオプション(フォーム要素のクラスなど)が含まれます。
引数とは、メソッドのカッコ内のやつです。
form_tag(引数はここだよ)
引数は、アクションへのパスとオプションのハッシュの2つなので、こうなる。
form_tag(
第1引数 - アクションへのパス(paramsの送り先のURL),
第2引数 - オプションのハッシュ(GETなどのHTTPメソッドやhtmlタグ内のclassの指定など
)
第1引数についてはURLを直書きすることもできるが、users_path
のように書くこともできるし、controller: "people", action: "search"
のように書くこともできる。
ただ、controller: "people", action: "search"
を何気なく書くと、エラーになってしまう。例えば、以下のように書くとactionが第2引数と認識されるのでエラーになる。
form_tag(controller: "people", action: "search", method: "get", class: "nifty_form")
よって、ハッシュを使うとよい。
form_tag({controller: "people", action: "search"}, method: "get", class: "nifty_form")
ぶっちゃけあまりform_tagなんて使わないと思うので、
form_withについても理解しておきたい。
ということで、form_withメソッドについても調べてみた。
form_with(model: nil, scope: nil, url: nil, format: nil, **options, &block)
ここでRuby自体の理解が大事になるのだが、こういった引数の書き方はキーワード引数という。キーワード引数を指定をしないとき、デフォルトの設定が採用される。
例えば、root_pathへのフォームを作成する場合、このようなコードとなる。
<%= form_with url: root_path do |form| %>
フォーム内容
<% end %>
この場合、例えばmodelについての引数は指定されていない。その場合、デフォルトのmodel:nil
が採用される。他のオプションについても、同様である。
その他のオプション等が何を意味するかについては、長くなりそうなので、後ほどの機会で。
分かりやすいので、そのまま掲載する笑
Railsには、〜フォーム要素を生成するためのヘルパーが多数用意されています。
これらの基本的なヘルパーは名前が_tagで終わっており (text_field_tagやcheck_box_tagなど)
それぞれただ1つの<input>
要素を生成します。
ただ、どちらかというと、tagよりfieldの方が目にすることが多いかもしれない。
fieldについては、後ほど触れる。
続ける。
これらのヘルパーの1番目のパラメータは、inputの名前と決まっています。
・・・たとえば、フォームに<%= text_field_tag(:query) %>
というコードが含まれていたとすると、
コントローラでparams[:query]
と指定すればこのフィールドの値にアクセスできます。
少し具体的にみてみる。
<%= form_with url:root_path do %>
<%= check_box_tag(:pet_dog) %>
<%= label_tag(:pet_dog, "I own a dog") %>
<%= check_box_tag(:pet_cat) %>
<%= label_tag(:pet_cat, "I own a cat") %>
<%= submit_tag("Search") %>
<% end %>
これで、こんなHTMLタグが生成される。
<form action="/" accept-charset="UTF-8" method="post">
<input type="hidden" name="authenticity_token" value="R0qYMo0//9dA1ECJ6G6muSXd9JXgss5z7DLPn6mwJL889Py252MQLGnhHoxGcC0fBNIHo8VOjaNU2560HjWe3A==">
<input type="checkbox" name="pet_dog" id="pet_dog" value="1">
<label for="pet_dog">I own a dog</label>
<input type="checkbox" name="pet_cat" id="pet_cat" value="1">
<label for="pet_cat">I own a cat</label>
<input type="submit" name="commit" value="Search" data-disable-with="Search">
</form>
そして、このフォームから送信されたparamsを取得するには、
〜tagの第1引数を使って、こんな感じで書いてあげれば大丈夫。
# pet_dogにチェックを入れて、pet_catにチェックをしていない場合
params[:pet_dog] #=> 1という値が取得できる
params[:pet_cat] #=> nilになる(paramsが送られていないため)
HTMLのinputタグは、山ほど種類がある。
20種類以上ある。
ということは、その数だけ、Railsのヘルパーもある。
Railsガイドでは、これだけ紹介されているが、あくまで一例。
<%= text_area_tag(:message, "Hi, nice site", size: "24x6") %>
<%= password_field_tag(:password) %>
<%= hidden_field_tag(:parent_id, "5") %>
<%= search_field(:user, :name) %>
<%= telephone_field(:user, :phone) %>
<%= date_field(:user, :born_on) %>
<%= datetime_local_field(:user, :graduation_day) %>
<%= month_field(:user, :birthday_month) %>
<%= week_field(:user, :birthday_week) %>
<%= url_field(:user, :homepage) %>
<%= email_field(:user, :address) %>
<%= color_field(:user, :favorite_color) %>
<%= time_field(:task, :started_at) %>
<%= number_field(:product, :price, in: 1.0..20.0, step: 0.5) %>
<%= range_field(:product, :discount, in: 1..100) %>
フォーム作成前に、どのようなinputタグがあるか、そしてそれに対応するrailsのヘルパーはどのようなものになるか、確認してみるといいかも。
emails_controller.rb
のsearchアクションで処理するやばい、この調子だと日がくれる...