0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Rails】form_with のオプションの指定方法について

Posted at

はじめに

こんにちは。アメリカにて独学でエンジニアを目指している者です。

以前の記事にてform_withのオプションはmodel:@userという指定方法を説明しましたが、Railsが自動で判断してcreateかupdateのどちらかのアクションを割り当てるというものでした。

しかし、当然Userのviewでしか使用できないためsessionコントローラーでログインページを作成するとなった場合には使用できません。

そこで本日は、model:@userを使う意義をあらめて確認したのち、今回のsessionコントローラーの場合はどのように定義をするのがよいかについて説明していきたいと思います。

model: @userを使う意義

もしmodel: @userと書いた場合、Railsは以下のような振る舞いを行います。

  1. @userという変数に格納されたActiveRecordオブジェクト(例えば、Userモデルのインスタンス)とフォームを関連付ける。
  2. フォームのフィールドとモデルの属性が1対1で対応するため、フォームで入力された値がモデルの属性に自動的に紐づく。
  3. バリデーションエラーがある場合などには、フォームとモデルが連携し、エラーメッセージの表示やハイライトが可能になる。

model: @userは、主に以下のケースで有用です。

  • 新規ユーザー登録フォーム(@userを新規作成し、User.newで生成したオブジェクトと関連付けてフォームを表示)
  • ユーザー情報編集フォーム(すでに保存されている@userを取得し、フォームを通じて更新)

このように、モデルの属性とフォームの入力欄を対応付け、フォーム送信後にモデルインスタンスを作成・更新するという流れが中心となります。

また、今回のようにSessionControllerでログイン機能を実装する場合は、そもそも@userというインスタンス変数が定義されていませんし、@sessionのようなものをActiveRecordで管理することも通常はありません。そのため、ログインフォームにmodel: @userを使う意義がなく、エラーとなってしまいます。

ログインフォームの特徴

ユーザーがアプリケーションにログインするとき、基本的には以下のステップを経ます。

  1. ユーザーのメールアドレスとパスワードを入力する。
  2. 送信ボタンが押されると、サーバー側にパラメータがPOSTされる。
  3. サーバー側でメールアドレスとパスワードが正しいかチェックする。
  4. セッションを作成し(または更新し)、そのユーザーがログイン済みであることを保持する。

この一連の流れの中では、データベースに新規レコードを作成したり、モデルのレコードを更新するといった操作は基本的に行いません。あくまで既存のユーザーに対して"ログイン"という操作を行うだけだからです。

SessionControllerにおけるform_with

一方、SessionControllerはセッションを扱うコントローラです。セッションは、そもそもデータベースのレコードではありません。ブラウザとサーバー間でやり取りされる一時的な情報であり、Cookiesなどを通じてログイン状態を保持します。

したがって、**セッションコントローラでmodel: @userと書いてしまうと、そもそも存在しない@userを参照しようとするため、意図した動作になりません。**また、以下の点で利点がありません。

  • ユーザーモデルを新規作成・更新しない
  • セッション用のオブジェクト(@sessionのようなもの)をActiveRecordで持つことは通常ない

そのため、セッションコントローラでログインフォームを扱う際は、url: オプションにログイン処理のパスを指定し、scope: でパラメータをどのようにネストするかを指定します。

例えば、

<%= form_with(url: login_path, scope: :session) do |f| %>
  <%= f.label :email %>
  <%= f.email_field :email %>

  <%= f.label :password %>
  <%= f.password_field :password %>

  <%= f.submit "ログイン" %>
<% end %>

この場合、フォーム送信時のパラメータ構造は下記のようになります。

params = {
  session: {
    email: "ユーザーが入力したメールアドレス",
    password: "ユーザーが入力したパスワード"
  }
}

コントローラでは、params[:session][:email]params[:session][:password] を使用してログイン認証処理を行う、という流れになります。

まとめ

  • ログインフォームでは、モデルのレコードを作成・更新しないため、model: @userを使う必要がない。
  • セッションコントローラでは、セッションの作成や削除などを行うだけで、ActiveRecordのモデルインスタンスとは直接連動していない。
  • そのため、form_withのオプションとしてurl:scope:を使って明示的にURLとネストキーを指定し、送信されたパラメータをログイン用に扱う。

これが、SessionControllerでform_with(model: @user)が使えず、form_with(url: login_path, scope: :session) のように書かれている理由です。ログイン処理の流れを把握し、モデルを不要とするケースではこうした書き方がRails的にも自然であると言えます.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?