はじめに
未経験からプログラミング学習中のkekiと申します。
Railsのログインの仕組みを理解する中で、form_with
の機能と個人的に難しかった疑問二点を記事にしてみました。
ログイン付近を学習中の方や、その復習をしたい方向けの内容です。
修正・追記あれば随時更新していきます。
form_withとは
Railsで情報を送信するためのヘルパーメソッドです。
form_with
を使うことにより、簡単に入力フォームに必要なHTMLを作成することができます。
かつてのform_tag
やform_for
メソッドをひとまとめにした大変便利なものです。
以下のような初期設定があります。
- HTTPメソッドの
POST
とPATCH
を自動的に切り替えてくれる - デフォルトではid属性やclass属性は付与されない
- デフォルトで
remote: true
が付与 - 関連モデルがある場合はモデルを指定し、ない場合はURLを指定する
主な機能
大きく6つにまとめました。
-
自動的に送信先のアクションをcreateかupdateに振り分けてくれる
おそらく最も恩恵を受けている機能です(参考記事はこちら)。
HTTPメソッドを個別に指定することもできます。
-
スコープを指定することができる
例えばusersコントローラとは別にsessionsコントローラを作り、ログイン画面でユーザーの情報を取得する際は以下のようなスコープの設定になります。
(詳細は下述します)<%= form_with scope: :session, url: sessions_path do |f| %> <%= f.text_field :name %> <%= f.submit %> <% end %>
-
form_withにはモデル属性にない入力フォームを追加できる
<%= form_with model: @user, url: users_path do |f| %> <%= f.text_field :name %> <%= f.text_field :hoge%> <%= f.submit %> <% end %>
-
デフォルトで
remote: true
設定(Ajaxでのリクエストがオン)になっている
→リモート無効のフォームにしたい時はlocal: true
に変更する
(詳細は下述します)
-
form_with
にはHTMLのclassやidを設定することができる(あまり使わないかも)<%= form_with model: @user, id: :任意のID, class: :任意のclass do |form| %> <%# フォームの部品 %> <% end %>
-
その他formタグで様々なオプションをつけることができる
-
form.html
でhtmlタグをつけると投稿の種類が変わる -
form.hidden_field
は非表示のフォームを作成し、ユーザーのidなどユーザーがフォームから入力しない情報をパラメータとして渡したいときに使える -
form.submit
は送信ボタンを作成する
-
自分の疑問点
<%= form_with(scope: :session, url: sessions_path, local: true) do |f| %>
-
local: trueって何してるの?
これはAjax(エージャックス)処理のオフを指しています。
Ajaxとは「JavaScriptでサーバー側との通信を非同期で行い、通信結果によって動的にページの一部だけ書き換える手法のこと」です。
form_with
はデフォルトでAjax処理が行われる設定なので、これを無効にする際にはlocal: true
が必要になります)local: true
を使ってる理由に関しては、以下の記事が詳しいのでぜひ参考にしてみてください!
form_withのlocal: trueって必要なん?これ何なん?(Ruby on Rails)
-
scope: :リソースの名前(ここではsession)って何してるの?
sessionsコントローラに相当するモデルが存在しないので、それに対応する受け皿となるフォームのオブジェクトを設定するために使用しています。
例を挙げます。
createアクションでユーザーのemailのパラメーターを取得するために、user = User.find_by(email: params[:session][:email].downcase)
のように指示されているとします。その時のリクエストを見てみると、次のようになります。Processing by SessionsController#create as HTML Parameters: {"utf8"=>"✓","authenticity_token"=>"fboHRR7XfTbsN7SxgjLgLx3uWDzzj7HC1hi8H/q3zX7mQpHU. 2B8HwgVBXYqyLEaSt4rwxNWJGHeoworyY8MoLw==", "session"=>{"email"=>"メールアドレス", "password"=>"[FILTERED]"}, "commit"=>"Log in"}
※この時の
form_with
での送信データはデータベースに保存されるわけではなく、cookieとしてブラウザに保存されていますコードの最後の行を見てみると、 “session”というキーの中に、更に"email"=>"メールアドレス", "password"=>"[FILTERED]"という別のハッシュが含まれているのが分かります。つまりハッシュの入れ子構造になっています。
params[:session][:email]
のように2つシンボルが続いているのは、入れ子になっている内部の方のキーを指しています。:sessionをform_with
内でスコープ指定することで、このような入れ子のハッシュのデータをデータベース無しで引き出すことができます。このようにscopeを加えると、生成されるhtmlの属性の構造が変わり、そのおかげでモデルが無くてもグループ化してデータを引き渡すことが可能です。
おわりに
form_with
のまとめでした。
まとめるにあたって、Ajax関連のJavaScriptの理解やログイン情報のデータの流れが少しわかってきたので、よい学習になりました。同じような未経験の学習者の方々の助けになれば幸いです。
他にも様々な機能やオプションがありますので、気になった方はぜひご自身でも調べてみてくださいね。
参考サイト
Rails 5.1〜7.0: ‘form_with’ APIドキュメント(翻訳)
Rails:form_withのオプションや特徴について整理
Ajaxとは?初心者向けに豊富な画像で仕組みを解説
form_withの:scopeオプション - プログラミング学習ノート