Bootstrapでflashメッセージを実装

概要

以下のflashメッセージをbootstrapで表示させる。

  • ログイン成功時・・・「ログインしました」
  • ログイン失敗時・・・「ログインに失敗しました」
  • ログアウト時・・・「ログアウトしました」
  • ユーザー登録時・・・「ユーザー登録が完了しました」
  • ユーザー登録失敗時・・・「ユーザー登録に失敗しました」

定義の追加

flashオブジェクトはハッシュ形式で保存されており、viewにメッセージを表示している。デフォルトではnoticeとalertキーしかない。bootstrapを使用する場合、下図のようなキーが使用できる。 f:id:meo2:20210502184841p:plain
これらのキーを使用するにはキーを許可する宣言をしなければならない。 application_controller.rbに以下の記述をする。

add_flash_types :success, :info, :warning, :danger

すると、success, :info, :warning, :dangerのキーが使用可能になる。

flashメッセージの表示をviewに追加

flashメッセージは複数のviewで使用するのでパーシャルを使う。
_flash_message.html.erbを作成しapplication_controllerで読み込む。

<% flash.each do |key, value| %>
  <div class="alert alert-<%= key %>"><%= value %></div>
<% end %>

keyとvalueはコントローラーから指定する。
例1

redirect_back_or_to root_path, success: 'ログインしました'

「success」がkeyで「ログインしました」はvalueで取得される。
例2

flash.now[:danger] = 'ログインに失敗しました'

「danger」がkeyで「ログインに失敗しました」がvalue

flashflash.nowの違い

flash[:danger]の場合は次のアクションまでメッセージを表示させる。 flash.now[:danger]とすると、次のアクションに遷移した時点でメッセージが消える。

パーシャルを読み込む

#...
   <body>
   <% if logged_in? %>
     <%= render 'shared/header'%>
   <% else %>
     <%= render 'shared/before_login_header'%>
   <% end %>
     <%= render 'shared/flash_message'%>
   <%= yield %>
     <%= render 'shared/footer'%>
  </body>
</html>

ログイン・ログアウト時にflashメッセージを表示させる

ログイン成功、ログアウト時はsuccessキーで表示。 ログイン失敗時はdangerキーで表示させる。

class UserSessionsController < ApplicationController
  skip_before_action :require_login, only: %i[create new]
  def new; end

  def create
    @user = login(params[:email], params[:password])

    if @user
      redirect_back_or_to root_path, success: 'ログインしました'
    else
      flash.now[:danger] = 'ログインに失敗しました'
      render :new
    end
  end

  def destroy
    logout
    redirect_to root_path, danger: 'ログアウトしました'
  end
end

renderとredirect_toの違い

上記を例とすると、
ログインできた場合
users#createアクション→root_path(users#index)→index.html.erbが描画される。
ログインに失敗した場合
users#createアクション→new.html.erbが描画される。という処理が流れる。 この処理から、redirect_to は、view の表示には直接は関係なく、新たな HTTPリクエストが発行される。*GETのみ(下図参照)
renderはcreateアクションに指定した値を直接表示させることがわかる。 f:id:meo2:20210502201821p:plain

ユーザー登録時にflashメッセージを表示させる。

ユーザー登録に成功したときと失敗したときに、メッセージを表示させる。

#...
  def create
    @user = User.new(user_params)
    if @user.save
      redirect_to login_path, success: 'ユーザー登録が完了しました'
    else
      flash.now[:danger] = 'ユーザー登録に失敗しました'
      render :new
    end
  end
#...

追記

ログイン前のヘッダーにあるログインボタンのhttpリクエストをgetにする。 ここがpostとかになっているとヘッダーのログインボタンからログインページにいったときにflashメッセージが表示されてしまう。

<%= link_to 'ログインする', login_path, method: :get, class: 'nav-link' %>

link_toメソッド

Railsでは主にviewファイルで使用され、引数を指定することでリンクを生成する。 <%= link_to 'リンクの文言', 'パス', class: 'クラス名', method: :HTTPリクエスト %>

methodでリンク先のルーティングを指定できる。