Rails Diary

プログラミングの学習記録です。

フラッシュメッセージまとめ

flashのキー

flashオブジェクトはハッシュ形式で保存されており、デフォルトではnoticeとalertがキーとして設定されている。

Bootstrapを使用することで、noticeやalert以外にもsuccess(緑),info(青),warning(黄),danger(赤)といったキーを使うことができる。

これらを使う場合にはflashのキーを新たに追加する宣言が必要になるため、所定の場所に記載すること。

application_controller.rb(宣言)

class ApplicationController < ActionController::Base
  add_flash_types :success, :info, :warning, :danger
end

複数のビューファイルで使うため、部分テンプレにしておくと便利。 layouts/_flash.html.erb

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

コントローラ

def create
  if user.save
    redirect_to root_path, success: "ユーザー登録に成功しました"
  else
content_tagメソッド

↑と比べてタグを簡潔に書くことができるメソッド

<% flash.each do |key, value| %>
  <%= content_tag(:p, value, class: "alert alert-#{key}") %>
# <%= content_tag(:タグ名, "表示する文字", class: "クラス名") %>
<% end %>

redirect_toとrenderのメッセージ表示タイミング

両者の違いは処理がもう一度同じコントローラを通過するかどうか。

flashメッセージはアクションが実行されたとき、次のアクションが実行されるまで保存される。次にアクションが実行されるときに削除される仕組み。

redirect_to

一度アクションが実行されてからビューが表示される。

saveが成功した場合、遷移先のパスへ飛び、遷移先を表示するアクションが実行される。

アクション実行 最初のアクション実行時のみflashメッセージが表示される
flashメッセージが保存され表示
アクション実行 2回目のアクション実行時にflashメッセージは削除される
flashメッセージが削除

render

renderメソッドでは、saveに失敗した場合に同じcreateアクション内で定義された値をnew.html.erbに渡すことになる。

renderはアクションを通さずに、ビューファイルをレンダリングするため、次にアクションが動いたタイミングでflashメッセージが表示されてしまう。
renderは表示された後、最初のアクションが実行される。
↑これを知らなかった。勘違いして覚えていた😰

①renderでflashメッセージを表示(1回目)
②topリンクを踏むとindexアクションが実行される
③アクションが実行されたため、flashメッセージが表示(2回目)
④新規登録のリンクを踏むと、usersのnewアクションが実行
⑤2回目のアクションが実行されたため、flashメッセージが消える

↑の様な形で、変なタイミングでflashメッセージが出てきてしまう。

else
  flash[:danger] = "ユーザー登録に失敗しました"
  render :new
end

↑この様に書くのは❌

このため、flash.nowを使用する

flash.nowを使うと、

flashメッセージが保存され表示 ②アクションの実行 ③flashメッセージが削除

コントローラ

def create
  if user.save
    redirect_to root_path, success: "ユーザー登録に成功しました"
  else
     flash.now[:danger] = "ユーザー登録に失敗しました"
    render :new
  end
end
flashflash.now

flash
次のアクションが動いた後のビューファイルにflashメッセージを表示するときに使う。

flash.now
現在のアクションで表示するビューファイルのみ有効なflashメッセージを表示させる時、renderで表示させたいときに使う。

他にも・・・

flash.keepやflash.discardなどあったけど、今回は割愛。 以下サイト参考に 【Rails】 完全保存版!flashの使い方とbootstrapで表示する方法

フラッシュメッセージにi18nを当てる

以前ビューごとの翻訳を定義する際はlazy lookupを用いて下記の様に記述していた。

ja:
  users:
    new:
      title: '新規登録'
      to_login_page: 'ログインページへ'

コントローラの翻訳を定義する場合も同じように書いてOK

config/locales/views/ja.ymlファイル

ja:
  users:
    new:
      (省略)
    create:
      success: 'ユーザー登録に成功しました'
      fail: 'ユーザーできませんでした'

コントローラ

def create
  @user = User.new(user_params)
  if user.save
    redirect_to root_path, success: (t'.success')

プチ豆知識

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

rederect_back_or_toの場合、add_flash_typesで宣言していなくてもflashの記載を省略できてしまうらしい😳

通常は

redirect_to root_path, flash: { success: 'ログインしました' }

参考にしたサイト

redirect_to使った時にBootstrap対応のフラッシュメッセージを表示させる - Qiita

【Rails】 完全保存版!flashの使い方とbootstrapで表示する方法

過去課題に重複箇所あり okmt-aya-26.hatenablog.com