先に結論から
- flashはアクションが動いた時に表示され、その場限りで破棄される
- flash.nowはアクションの有無に関わらず表示され、その場限りで破棄される
flashメッセージとは
画面遷移時にユーザーに向けて発信される簡易的なメッセージのこと。 ログインの成功時やデータの登録時など、ユーザーに対して逐次状況を伝える手段として主に用いられます。 実体としてはサーバー上のセッション情報の一部として保持されて、リクエストの度にクリアされるという性質を持っています。 簡単に言うと表示されたら破棄されるその場限りのメッセージです。
flashとflash.now
具体的なコードを書きながらflashメッセージについてまとめてみます。
想定するシチュエーションとしては以下の通りです。
投稿モデルに対して一件の投稿を登録し、登録が完了したら「登録しました」というflashメッセージを画面に表示し、投稿一覧画面に遷移してくる
何らかのバリデーションエラーにより登録が失敗したら、「登録に失敗しました」というflashメッセージを画面に表示し、新規投稿画面を呼び出す
# app/controllers/posts_controller.rb class PostsController < ApplicationController def create @post = Post.new(create_post_params) if @post.save redirect_to posts_url, flash: {success: '登録しました' } else flash.now[:danger] = '登録に失敗しました' render :new end end private def create_post_params params.require(:post).permit( :name, :status ) end end
上記コードを見て分かる通り、登録成功時には flash: {success: '登録しました' } 登録失敗時には flash.now[:danger] = '登録に失敗しました' という二つの書き方をしていることがわかります。 それではこの二つの書き方にはどのような違いがあるのでしょうか?
redirect_toとrenderの違いについて
二つの違いについて説明する前にまず、redirect_toとrenderの違いについて簡単に説明を挟んでおこうと思います。
redirect_to
引数として次にアクセスしてほしいURLの文字列を渡して、リダイレクト(HTMLの代わりにURLを返却するHTTPレスポンス)を発生させるメソッド。 リダイレクトを受け取った場合ブラウザは、自動的に返却されたURLに対してGETでリクエストをしなおす。 この場では端的に、渡したURLに対してGETリクエストを行い、その先のアクションを実行するものと理解するのがいいかと思います。
render
指定したテンプレート(viewファイル = HTML)をブラウザに渡してレンダリングを実行するメソッド。 これもこの場では端的に指定したテンプレートを呼び出すものと理解するのがいいかと思います。 純粋なテンプレートの呼び出しを行うのみなのでアクションの実行を介しません。
flashとflash.nowの違いについて
flashとflash.nowでは、メッセージを表示するきっかけが異なります。 flashメッセージと前段でおさらいしたredirect_to, renderに焦点を当てながら、改めてコードを分解していきます。
# app/controllers/posts_controller.rb class PostsController < ApplicationController def create @post = Post.new(create_post_params) if @post.save redirect_to posts_url, flash: {success: '登録しました' } else flash.now[:danger] = '登録に失敗しました' render :new end end private def create_post_params params.require(:post).permit( :name, :status ) end end
投稿の登録が成功した場合
- redirect_to posts_urlにより投稿一覧画面に遷移。(アクションの実行)遷移したページでflashメッセージが表示される(メッセージ破棄)
- 異なるページに遷移する(アクションの実行)
- 1の時点でflashに格納されたメッセージが破棄されているため、遷移したページでメッセージは表示されない
投稿の登録が失敗した場合
- render :newにより新規投稿画面がレンダリングされる。新規投稿画面でflashメッセージが表示される(メッセージ破棄)
- 異なるページに遷移する(アクションの実行)
- 格納されたメッセージが破棄されているため、遷移先のページではメッセージは表示されない
投稿失敗時にflash.nowではなく、flashでメッセージを表示しようとした場合
- render :newにより新規投稿画面がレンダリングされる。新規投稿画面でflashメッセージが表示される
- 異なるページに遷移する(アクションの実行)
- 遷移したページでも再度メッセージが表示される(メッセージ破棄)
- 異なるページに遷移する(アクションの実行)
- 3のタイミングで格納されたメッセージが破棄されているため、遷移先ではメッセージは表示されない
このようにflashとflash.nowでは、アクション(リクエスト)を跨ぐか跨がないかによりメッセージが表示・破棄されるタイミングに違いがあります。
まとめ
- flashはアクションが動いた時に表示され、その場限りで破棄される
- flash.nowはアクションの有無に関わらず表示され、その場限りで破棄される