【Rails】flashの使い方と仕組みを徹底解説【初心者向け】

Ruby on Rails

Ruby on Railsの学習初期で現れるflashは初心者には特殊な変数に見えますよね。
flashの活用はログイン・ログアウトやデータの更新処理の後にユーザに親切なメッセージを表示するための必須スキルです。

本記事ではflashの使い方と仕組みを初心者向けに解説します。
Railsアプリケーション開発でflashを使うための知識を身に着けておきましょう。

スポンサーリンク

フラッシュメッセージとは

フラッシュメッセージは、ログインやデータの更新などユーザのアクションに対する結果をかんたんなメッセージとして表示する機能です。

フォームからデータの追加・更新・削除などを画面からおこなった場合に、成功したのか失敗したのか、何か表示しないとユーザは迷ってしまいます。
普段は表示しないけど、特定のアクションの後だけ表示する一時的なメッセージがフラッシュメッセージです。

Rails の flashとは

Rails の flash はリクエストをまたいだ先の画面で使いたいデータを扱うためのメソッドです。
ほとんどの場合、扱うデータはメッセージです。次の画面で一時的にメッセージを表示したい場合に使用します。

「リクエストをまたぐ」メッセージのイメージ

イメージとしては以下のとおりです。

  1. 1つ目のリクエストを受け付けたタイミングでRailsアプリがメッセージを作りブラウザにレスポンスする
  2. 2つ目のリクエストを送信し、レスポンスのなんかに①で作成したメッセージをHTMLに埋め込む

以上のように、リクエストをまたいで表示したいメッセージがある場合に flash を使用します。

インスタンス変数ではリクエストをまたげない

Railsでアプリケーションを開発する場合、Rubyで記述するため「インスタンス変数」でデータを保持すれば同じことができるのでは?というのが初心者にはよくある誤解です。

Rails に限らず Web アプリケーションでは、リクエスト間でデータを覚えていることはありません。
「HTTPはステートレスである」と言います。

1つ目のリクエストでインスタンス変数にメッセージを代入しても、2つ目のリクエストでそのインスタンス変数にアクセスすると空になっています。

flash はこれを防ぐために用意された機構となっています。

sessionではデータが残り続ける

Railsを勉強した人は session を使えばリクエストをまたげるのでは?と考えるかもしれません。
それは正しいです。

しかしsession の場合は明示的にデータを消去しない限り残り続けるため、メッセージは表示され続けます。

flashの場合は次のリクエストに対してレスポンスしたら自動的に消去されるため、プログラマーが明示的に消去しなくても一時的に表示するメッセージを実現できます。

flashの使い方

コントローラでの値の設定

flashはハッシュと同様の形式で利用できます。

flash[キー] = "メッセージ"

例えば以下のように設定します。

flash[:notice] = "登録しました"

ビューでの値の参照

flashはハッシュのように参照できます。

<%= flash[キー] %>

例えばビューでは以下のように参照してデータをHTMLに埋め込めます。

<%= flash[:notice] %>

flash はハッシュ型で値を返すため、以下のように each メソッドを使ってすべてのデータを表示することができます。

<% flash.each do |message_type, message| %>
    <div><%= message %></div>
<% end %>

flash.now

flashの仲間にflash.nowがあります。
flashが「次のリクエスト」まで残るのに対して、flash.nowは「現在のリクエスト」に対する処理の間のみ残ります。つまり、次のリクエスト以降は消えてしまうデータとなります。

flash.nowへのコントローラでの値の設定

flash.nowもflashと同様にハッシュのように使用できます。

flash.now[キー] = "メッセージ"

例えば以下のように設定します。

flash.now[:alert] = "登録に失敗しました"

flash.nowからビューでの値の参照

ビューでの参照はflashと全く同じ形式で行います。
flash.now[キー] ではなく以下のようになるのがポイントです。

<%= flash[キー] %>

例えば以下のように参照します。

<%= flash[:alert] %>

flash・flash.nowどちらで設定しても参照するときは flash[キー]

flash[キー] = "メッセージ"

でセットしても、

flash.now[キー] = "メッセージ"

でセットしても、参照するときは

 <%= flash[キー] %>

で参照するのがポイントです。

この性質があるため、どちらでセットしても共通のビューで表示できるようになります。
次に利用パターンを説明するのでこれがなぜうれしいかを実感できます。

典型的な利用パターン

典型的な利用パターンを紹介します。
以下はPostモデルのデータをフォームから受け取り、保存する処理です。

def create
  @post = Post.new(post_params)
  if @post.save
    # 保存に成功したとき
    flash[:notice] = "投稿を作成しました"
    redirect_to @post
  else
    # 保存に失敗したとき
    flash.now[:alert] = "投稿の作成に失敗しました"
    render :new
  end
end

@post.save メソッドで保存を行ない、以下のように分岐します。

  • 保存に成功したときは、:notice キーで flash に成功メッセージを設定し、詳細ページへリダイレクト
  • 保存に失敗したときは、 :alert キーで flash.now に失敗メッセージを設定し、:new を render

flashとflash.nowのそれぞれでメッセージを設定していますが、参照するときはどちらも flash から取得できるため、以下のように記述できます。

<% flash.each do |message_type, message| %>
  <div><%= message %></div>
<% end %>

flashかflash.nowでセットしたメッセージデータをeachで一つずつ取得し、divタグで囲んで表示しています。

redirect_to なら flash、render なら flash.now でメッセージをセットする

ほとんどの場合、flashは以下の組み合わせになります。最初のうちは覚えてしまってもいいでしょう。

  • リダイレクトする場合(redirect_toなど)は flash でメッセージをセット
  • render する場合は flash.now でメッセージをセット

よほど特殊な場合を除いて上記の組み合わせだけになります。
理由は redirect_to と render それぞれのリクエスト回数の違いによります。

redirect_to の場合は GET リクエストが発生するため次のリクエストまでのこる flash を使う

redirect_to の場合はGETリクエストが発生し、そのGETリクエストで表示する画面に埋め込むメッセージをセットしたいので flash を使用します。

リダイレクトについて詳しく知りたい場合は以下の記事を参照してください。
» redirect_to によるリダイレクトの方法を徹底解説【Ruby on Rails】

render の場合は追加リクエストがないため次のリクエストまで残らない flash.now を使う

render の場合はそのrenderで指定したビューファイルに埋め込みたいため新たなリクエストは発生しません。
そのためflash.nowを使用します。

renderについて詳しく理解したい場合は以下を参照してください。
» 【Rails】renderの解説!基本・引数・オプションを完全理解!
» 【Rails】render メソッドの引数のルールを徹底解説!!【初心者向け】

特に render は省略されることがあるため混乱する可能性があります。
上記記事でrenderのルールについて理解しておくのが重要です。

まとめ

Ruby on Rails の flash の使い方と仕組みを解説しました。

まとめると以下の通りです。

  • ログイン後や更新後などに一時的に表示するメッセージをフラッシュメッセージという
  • Rails では flash を使ってフラッシュメッセージを表示する
  • flash は次のリクエストまで、flash.now は現在のリクエストまでが有効期限で、その後は自動的に消去されるデータを扱える
  • redirect_to のときは flash、render のときは flash.now を使う

Railsアプリケーション開発では flash は必ず使いますので、どんどん使ってみてしっかりと理解しておきましょう。

タイトルとURLをコピーしました