LoginSignup
181
165

More than 3 years have passed since last update.

【Rails】flashメッセージを使用して簡易メッセージを表示させる詳しい方法と解説

Last updated at Posted at 2019-04-27

はじめに

flashメッセージとは、アクション実行後に簡単なメッセージを表示させるRailsの機能です。
なお、deviseの機能(ユーザー作成やログイン等)を使用した場合とそうでない場合で実装方法が違いますが、今回はdeviseを使用していない場合のflashメッセージの表示方法について説明していきます。
また前提として、今回はview部分をhaml記法にて記述します。

やりたいこと

Sendボタン押下にてメッセージを投稿した際に、flashメッセージが画面上部に表示されるよう実装します。今回はメッセージの投稿成功時と失敗時でメッセージが変わるようにします。

・投稿に成功した場合
水色の「メッセージが送信されました」部分がflashメッセージです。
image.png

・投稿に失敗した場合
オレンジ色の「メッセージを入力して下さい」部分がflashメッセージです。
image.png

「flash」を使用してflashメッセージを表示させてみる

大まかな流れは以下のとおりです。

  1. controllerを編集する
  2. viewを編集する
  3. CSSを追加する

1. controllerを編集する

flashメッセージ使用するためには、「FlashHash」というオブジェクトを使用します。
こちら、名前の通りハッシュオブジェクトです。
後述しますが、処理が成功した場合には[:notice]キーを、失敗した場合には[:alert]キーを使用します。

「Flash」や「FlashHash」についての詳細はこちらに書いてありますので、「Flash」でサイト内検索してみて下さい。
参考:Ruby on Rails ガイド

さて、本題に入っていきます。
結論から言うと、完成形の例はこんな感じです。
これから一つ一つ見ていきます。

messages_controller.rb
1   def create
2     @message = @group.messages.new(message_params)
3     if @message.save
4       redirect_to group_messages_path(@group), notice: 'メッセージが送信されました'
5     else
6       flash.now[:alert] = 'メッセージを入力してください。'
7       render :index
8     end
9   end

投稿に成功した場合

例でいうと、3〜4行目が投稿に成功した場合の処理になります。
ただ、以下のほうがわかりやすいかと思うので、例とは少し違う書き方で説明します。

messages_controller.rb
3   if @message.save
4     # 投稿に成功した場合
5     flash[:notice] = 'メッセージが送信されました'  #ここが例と違う
6     redirect_to group_messages_path(@group) #ここが例と違う

5行目でflashオブジェクトのキーである[:notice]に表示したいメッセージをvalueとして追加しています。
6行目ではメッセージ登録後、リダイレクトをしてindex.htmlに遷移しています。

結果は同じですが、上記の処理は一行で記述できるので、完成形の例では以下のようにしています。こっちのほうがスッキリです。

messages_controller.rb
4    if @message.save
5      redirect_to group_messages_path(@group), notice: 'メッセージが送信されました'

投稿に失敗した場合

5〜7行目が投稿に失敗した場合の処理になります。

messages_controller.rb
5    else
6      flash.now[:alert] = 'メッセージを入力してください。'
7      render :index

6行目でflashオブジェクトのキーである[:alert]に表示したいメッセージをvalueとして追加しています。
成功時とは違い、flash.nowを使用しています。(※)
7行目ではメッセージ登録後、renderをしてindex.htmlに遷移しています。

※flashとflash.nowの使い分けについては後述

2. viewを編集する

controllerが完成したので、application.htmlを編集して画面に表示します。
まず最初に、追加する箇所はこんな感じ。

application.html.haml
~~~~~~~~~~~~~~~~~~略~~~~~~~~~~~~~~~~~~
1  %body
2    #----------ここから----------
3    .notifications
4      - flash.each do |key, value|
5        = content_tag(:div, value, class: key)
6    #--------ここまでを追加--------
7    = yield

3~5行目のflashメッセージ部分は、HTMLに変換されると以下のような形になります。

application.html
<div class="notifications">
 <div class="notice">メッセージが送信されました</div>
</div>

application.htmlはどのファイルを読み込む場合でも読み込まれる共通のviewです。
「= yeild」にて他のviewファイル(index.htmlとか)を読み込む事によって、そのviewファイルの内容が画面に表示されます。
今回は画面の上部にflashメッセージを表示させたいので、「= yeild」の前(他のviewファイルを読み込む前)にflashメッセージを実装しています。

それでは、実装箇所を一つ一つ見ていきます。

解説

3行目でflashメッセージの親要素となるdivタグを定義します。

application.html.haml
  .notifications

4行目でflashオブジェクトを呼び出しています。
投稿成功の場合、この時点で、keyに"notice"、valueに"メッセージが送信されました"が入ります。

application.html.haml
  .notifications
    - flash.each do |key, value|

5行目でcontent_tagを使用してflashメッセージを表示させるためのdivタグを作成します。前述の通り、keyに"notice"、valueに"メッセージが送信されました"が入っていますので、classが"notice"、表示させたい内容が"メッセージが送信されました"となります。

application.html.haml
  .notifications
    - flash.each do |key, value|
      = content_tag(:div, value, class: key)

ちなみに、content_tagはHTMLタグを生成するメソッドで、以下のように使います。

content_tag(作成するタグの種類△表示したい内容△class等のオプション)
※△は半角スペース

3. CSSを追加する

上記のviewの実装にて追加したクラスにCSSを追加します。
ここは自由にCSSをあててください。一応、以下は例です。

application.scss
.notifications {
  color: $white;
  text-align: center;  

  .notice {
    background-color: lightBlue;
  }

  .alert {
    background-color: alert_orange;
  }
}

以上で、flashメッセージを表示させることが出きます。

flashとflash.nowの使い分け方は?

結論から言うと、以下のように使い分けます。
  ・flash:    リダイレクトする時
   ・flash.now: renderする時

なぜか?
それを理解するためには、以下の2つを理解する必要があります。

  • リダイレクトとrenderの挙動の違い
  • flashの特徴

リダイレクトとrenderの挙動の違い

こちらについては、以下の記事がわかりやすかったです。

参考:【Rails】renderとredirect_toの違いと使い分け

一部抜粋せていただくと、、、"今回は"以下のような流れで次の画面を描写します。

・render     : controller(createアクション) → view(index.html)
・redirect_to   : controller(createアクション) → URL → route → controller(indexアクション) → view(index.html)

リダイレクトの場合、createアクションの直後にrouteを経由して次のindexアクションが実行される事がわかります。
言い換えれば、createアクションとindexアクションは別のリクエストとなります。
一方renderでは、createアクションの直後にindex.htmlを表示しています。
こちらは同じリクエストとなっています。

これを踏まえてflashの特徴を見ていきます。

flashとflash.nowの特徴について

■flashの特徴
flashについて、Railsのドキュメントには以下の様に記載されています。

flashはセッションの中の特殊な部分であり、リクエストごとにクリアされます。つまりflashは「直後のリクエスト」でのみ参照可能になるという特徴を持ち、エラーメッセージをビューに渡したりするのに便利です。

■flash.nowの特徴
flash.nowについて、Railsのドキュメントには以下の様に記載されています。

デフォルトでは、flashに値を追加すると直後のリクエストでその値を利用できますが、次のリクエストを待たずに同じリクエスト内でこれらのflash値にアクセスしたい場合があります。たとえば、createアクションに失敗してリソースが保存されなかった場合に、newテンプレートを直接描画するとします。このとき新しいリクエストは行われませんが、この状態でもflashを使ってメッセージを表示したいこともあります。このような場合、flash.nowを使えば通常のflashと同じ要領でメッセージを表示できます。

つまり今回で言うと、、、
メッセージ投稿成功時はリダイレクトしており、直後のリクエスト後(indexアクション後)にflashメッセージが参照可能となっているため、flashを使用しています。
また、メッセージ投稿失敗時には、同じリクエスト内でflashメッセージを表示したいので、flash.nowを使用しています。

参考:Ruby on Railsドキュメント

まとめ

備忘として、flashメッセージの実装方法について纏めました。
理解不足により、認識が間違っている点や不明点等あればご指摘下さい。

181
165
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
181
165