質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.63%

form_forについて、エラーを解決したい。

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 118

yume0409

score 17

form_forについてです。

解決したい内容

最終的にやりたい内容はログイン機能でメールアドレスかパスワードが間違っていたらエラーメッセージを出すようにしたいです。
ログインはdeviseを使用しました。
今はエラーメッセージより正常にログインのビューを表示させたいです。
コントローラーをカスタマイズすることは出来ました。

sessions/new.html.haml

.new
  %h4 ログイン
  = form_for(@user) do |f| 
    - if @error_message
      .error
      = @error_message
    .field
      = f.label :email
      %br/
      = f.email_field :email, autofocus: true, autocomplete: "email", class: "text"
    .field
      = f.label :password
      %br/
      = f.password_field :password, autocomplete: "current-password", class: "text"
    - if devise_mapping.rememberable?
      .field
        = f.check_box :remember_me
        = f.label :remember_me


sessions.controller.rb

def new
    @user = User.find_by(email: params[:email], password: params[:password])
    if @user
      redirect_to :root
    else
      @error_message = "エラー"
      @email = params[:email]
      @password = params[:password]

      render "devise/sessions/new"
  end
end


コントローラーの2行目をfind_byにすると下記のエラーメッセージが出ます。
エラー個所はビューの3行目のform_forなのでその引数に当たる、@userがおかしいんだと思います。

ArgumentError in Users::Sessions#new
First argument in form cannot contain nil or be empty


なのでコントローラーの2行目をnewに変えてみました。

def new
    @user = User.new
    if @user
      redirect_to :root
    else
      @error_message = "エラー"
      @email = params[:email]
      @password = params[:password]

      render "devise/sessions/new"
  end
end


そしたらエラーはなくなるのですが、恐らく、コントローラーの4行目が動いてると思いますが、ルートにリダイレクトされます。
ログイン押しても瞬時にルートに遷移されます。
これをredirect_to "/users/sign_in"に変更すると

このページは動作していません
localhost でリダイレクトが繰り返し行われました。


となります。
これにずっと悩んでいるのでご教授いただけると幸いです。
よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

0

yume0409さんの見立てがあっていると思うので、それを前提に回答します。

ログイン処理は概ね以下の流れになると思います。

  1. newアクションで@userインスタンスをセット
  2. sessions/new.html.hamlでフォームを表示
  3. ユーザー名とパスワードを入力してフォームを送信
  4. createアクションにリクエストを送信
  5. ログイン処理をして、エラーならエラーメッセージを返す
  6. ログインが成功した場合はログイン後のページ、エラーの場合はsessions/new.html.hamlでエラーメッセージを表示

今のコードですと、newアクションでインスタンス変数のセットとログイン処理を一緒に実装しているので、うまく行っていないように見えます。

インスタンス変数の設定とログイン処理をわけて実装するとRailsらしい書き方になるので、SessionsControllerは以下のようにするといいと思います。
(コードは既存のコードを再利用したので、適宜修正する必要があるかもしれません。)

# SessionsController

def new
  @user = User.new
end

def create
  @user = User.find_by(email: params[:email], password: params[:password])

  if @user
    redirect_to :root
  else
    @error_message = "エラー"
    @email = params[:email]
    @password = params[:password]

    render "devise/sessions/new"
  end
end

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/02/15 15:22

    ありがとうございます。
    エラーメッセージが出せるようになりましたが、メールアドレスとパスワードが合っている場合もエラーメッセージが出ます。
    loginボタンを押してチャットメインへ遷移されない状態になっています。
    コントローラーのcreateにif文がありますが、何か記述のミスはありますでしょうか・・・?

    キャンセル

  • 2020/02/15 16:34 編集

    回答にも書きましたが、createアクションのコードはyume0409さんのコードを利用したものなので、ご自身の設定に応じて修正する必要があると思います。
    エラーメッセージが表示されるということはログイン処理ができていないので、ログイン判定を修正してみてください。
    form_forのエラーは解決できたと思うので、一旦この回答は解決済みにして、別の質問をたてたほうが課題を混同しないのでいいと思います。

    キャンセル

0

form_forの第一引数にnilを渡すことはできません。

@user = User.find_by(email: params[:email], password: params[:password])

の結果がnilになっている場合、@user = User.newを実行するようなコードを追加してみましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.63%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる