Chapter 16

3-6. フラッシュメッセージ追加

Masuyama
Masuyama
2022.10.15に更新

フラッシュメッセージ追加

現状、ログインページからログインしようとした際に認証情報が誤っていても、何も表示されません。
また、ログインに成功したとしてもただトップページにリダイレクトされるように見え、ログインできているかが分かりません。

これだとユーザーからはログイン機能の使い勝手が分かりにくいため、
ログイン成功時・失敗時には、その旨が画面上部にフラッシュメッセージとして表示されるようにしましょう。

テスト修正

そろそろ RSpec を使ったテストの書き方にも慣れてきたと思うので、
テスト駆動開発の方式に倣って先にテストを修正して仕様を確定させましょう。

spec/system/users_spec.rb の中で
describe 'ログイン機能の検証'というブロックにテストを追加していきます。

修正後のテストは以下のようになります。

spec/system/users_spec.rb

  ...
  describe 'ログイン機能の検証' do
    before do
      create(:user, nickname: nickname, email: email, password: password, password_confirmation: password)

      visit '/users/sign_in'
      fill_in 'user_email', with: email
      fill_in 'user_password', with: 'password'
      click_button 'ログイン'
    end

    context '正常系' do
      it 'ログインに成功し、トップページにリダイレクトする' do
        expect(current_path).to eq('/')
      end

      it 'ログイン成功時のフラッシュメッセージを表示する' do # 追加
        expect(page).to have_content('Signed in successfully')
      end
    end

    context '異常系' do
      let(:password) { 'NGpassword' }
      it 'ログインに失敗し、ページ遷移しない' do
        expect(current_path).to eq('/users/sign_in')
      end

      it 'ログイン失敗時のフラッシュメッセージを表示する' do  # 追加
        expect(page).to have_content('Invalid Email or password')
      end
    end
  end

この時点では、まだフラッシュメッセージを実装していないためテストにコケることを確認してください。

$ bin/rspec
...
Finished in 10.2 seconds (files took 0.31626 seconds to load)
12 examples, 2 failures

Failed examples:

rspec ./spec/system/users_spec.rb:105 # User ログイン機能の検証 正常系 ログイン失敗時のフラッシュメッセージを表示する
rspec ./spec/system/users_spec.rb:116 # User ログイン機能の検証 異常系 ログイン失敗時のフラッシュメッセージを表示する

次にフラッシュメッセージを実装し、テストを通していきます。

実装追加

部分テンプレート作成

まずは、フラッシュメッセージを表示するための部分テンプレートを作成します。

app/views/sharedというディレクトリを作成し、 _flash.html.erbというファイルを作成してください。
中身は以下の通りにします。

app/views/shared/_flash.html.erb

<% if flash[:notice] %>
  <div class="p-4 mt-3 mb-4 mx-3 text-sm text-blue-700 bg-blue-100 rounded-lg dark:bg-blue-200 dark:text-blue-800" role="alert">
    <%= flash[:notice] %>
  </div>
<% end %>
<% if flash[:alert] %>
  <div class="p-4 mt-3 mb-4 mx-3 text-sm text-red-700 bg-red-100 rounded-lg dark:bg-red-200 dark:text-red-800" role="alert">
    <%= flash[:alert] %>
  </div>
<% end %>

部分テンプレート読み込み

フラッシュメッセージ用の部分テンプレートはすべての画面で使い回すものですので、
すべての画面に表示するための view である app/views/layouts/application.html.erb に手を加えます。

以下のように、main タグの上に 1 行を追加してください。

app/views/layouts/application.html.erb

...
<body class="h-screen bg-blue-50">
  <%= render 'shared/flash' %>
  <main class="container mx-auto mt-20 py-8 px-5 flex items-center justify-center">
    <%= yield %>
  </main>
</body>

これで、フラッシュメッセージに内容が入ってきた時には常に一番上に表示されるようになります。

テスト実行 (成功)

実装は完成したはずなので、テストを実行しておきましょう。

もちろん、先にブラウザを使って手動で動作確認もできるためそれでも OK なのですが、
表示有無の機能自体については RSpec での自動テストの方が早く確実にチェックできるため、自動テストに頼ることをおすすめします。

$ bin/rspec spec/system/users_spec.rb
...
  ログイン機能の検証
    正常系
      ログインに成功し、トップページにリダイレクトする
      ログイン成功時のフラッシュメッセージを表示する
    異常系
      ログインに失敗し、ページ遷移しない
      ログイン失敗時のフラッシュメッセージを表示する

Finished in 6.22 seconds (files took 0.39357 seconds to load)
12 examples, 0 failures

テストに無事に通ることを確認しました。

次は、RSpec のテストでは確認していない見た目について、ブラウザでチェックします。

動作確認

では、ログインページ http://localhost:3000/users/sign_in にアクセスして確認していきます。
(ログイン済みの場合は、ログアウトしておきましょう)

まずは、ログインフォームに何も入力せずに「ログイン」ボタンを押してください。
メールアドレス、またはパスワードが無効である旨の (alert レベルの)フラッシュメッセージが表示されます。

image

次に、エラーがなかった場合のフラッシュメッセージを確認します。
作成済みユーザーの認証情報を用いてログインし、ログインに成功した旨の (notice レベルの)フラッシュメッセージが表示されることを確認します。  
(一度もユーザーを作成していなければ、先に /users/sign_up から一度ユーザーを作成しておきましょう)

image

これで、フラッシュメッセージを表示させるという仕様は実現できていることを画面からも確認できました。

変更をコミット

ここまで完了したら、変更をコミットしておきましょう。

$ git add .
$ git commit -m "フラッシュメッセージを表示できるように変更"
$ git push

宿題

部分テンプレート

Rails のアプリでは、view を使いまわせるところは使い回し、記述の重複を出来るだけ少なくすることを基本的に目指します。
そのため、今回作った部分テンプレートが便利になります。

部分テンプレートは基本中の基本ですので、使い方を忘れている場合は復習しておきましょう。

flash とは

Rails における flash とは、アクション実行後にメッセージを一時的に表示させる仕組みです。

devise を使うと flash に関する設定は特にしなくても使えましたが、devise に関連しないアクションで使う時には自分で設定する必要があります。
よく使われる仕組みですので、この機会に覚えておきましょう。