【Rails入門説明書】flashについて解説
はじめに
Webサービスを作成するとき、パフォーマンスはとても重要です。
しかし、データの量やサーバーのスペックなどの問題で、どうしても待ち時間が発生することがあるでしょう。
そんなときでも、じつは、ただ一言メッセージがあるだけで、ユーザーは納得して待ってくれることが多いものです。
また、何らかの処理をしたとき、何をしたかのメッセージを表示しなければ、どれほど処理が早くても、勝手に処理をされたという指摘を受けることがあります。
Webサービスで表示するメッセージには、それだけの影響力があるものなのです。
今回は、そんなWebサービスの印象を決めるメッセージを表示するflashメソッドについて、詳しく解説します。
flashメソッドを使ってみる
flashメソッドは、処理結果などをユーザーに伝えるメッセージを表示することができるメソッドです。
具体的にどんなものなのか、まずは作って動かしてみましょう。
環境構築
コマンドプロンプトで、以下のコマンドを実行しましょう。
[bash]rails new flash_test
cd flash_test
rails generate scaffold Item title:string price:integer
rake db:migrate
[/bash]
念のため、「rails s」でサーバーを起動し、ブラウザで「localhost:3000/items」へアクセスして表示されることを確認しておきましょう。
比較のために、1件新規追加して動きを確認しておいてください。
「New item」をクリックして新規登録画面へ遷移し、itemを1つ登録すると、登録した内容が表示される詳細画面へ遷移します。
「Create Item」をクリック
この画面の表示を憶えておいてください。
flashメソッドでメッセージを表示する
では、構築したテスト環境で、メッセージ表示をしてみます。
新規登録完了したときに、「created item!」と表示してみます。説明は後で行いますので、まずは以下の(1)の行をそれぞれ追加して、動かしてみてください。
(app/controllers/items_controller.rb)
:
def create
@item = Item.new(item_params)
respond_to do |format|
if @item.save
flash[:complete] = “created item!” # (1)
format.html { redirect_to @item, notice: ‘Item was successfully created.’ }
format.json { render :show, status: :created, location: @item }
else
format.html { render :new }
format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
:
(app/views/items/show.html.erb)
<%= flash[:complete] %> <!– (1) –>
<%= notice %>
:
「localhost:3000/items」の画面の「New item」をクリックして新規登録画面へ遷移して、itemを1つ登録してみましょう。
「Create Item」をクリックして詳細画面へ遷移したときに、「created item!」とflashメソッドで登録したメッセージ(flashメッセージ)が表示されます。
なお、ここでF5キーを押して再表示すると、メッセージは表示されなくなります。
flashメソッドは、このように「あるアクションの後に1度だけメッセージを表示する」ために使うことがほとんどなのです。
https://web-camp.io/magazine/archives/12654
flashメソッドの構文と使い方
では、flashメソッドを使いこなすため、詳細な説明をしていきましょう。
まずは基本的な構文です。
flash[キー] = メッセージ
コントロールなどでこの形でメッセージを登録すれば、その後のViewファイルで、次のような形で参照することができます。
<%= flash[キー] %>
とてもシンプルで分かりやすいかと思います。
なお、個の構文を見て、flashがハッシュのようだと思った人がいるかもしれません。
flashメソッドは、まさにハッシュと同じようにメッセージを保持してくれるメソッドなのです。ただし、通常のハッシュと違い、flashメソッドの保持するメッセージには寿命があります。
メッセージの寿命
flashメソッドに格納されたメッセージは、原則として次のアクションまで有効になっています。
つまり、あるアクションでメッセージを登録すると、そのアクションによって遷移する先のページで表示され、その次に遷移する先には、表示されないということになります。前項でF5キーを押した場合のように、たとえ遷移先が同じページ(flash[キー]を参照するページ)であっても、メッセージを登録する処理が行われない限りは、表示されません。
では、改めて動かして確認してみましょう。
一覧表示のViewファイルに、メッセージ表示の1文を追加します。
(app/views/items/index.html.erb)
<%= flash[:complete] %> <!– (2) –>
<%= notice %>
:
新たに登録して、「Back」をクリックしてみましょう。
「Back」クリック
一覧画面にflashのメッセージ表示用の1文を追加しているのにもかかわらず、一覧画面へのページ遷移が発生したため、メッセージは表示されていません。
flashメソッドで登録したメッセージの寿命は、ページ遷移後の表示1回だけなのです。
renderの場合
flashメソッドでメッセージを登録したコントローラを見てみると、登録後のページ遷移にredirect_toを利用しています。これは、ページ遷移の一般的な手段です。ただ、よくある表示の切り替え方法として、renderメソッドの使用があります。(redirect_toとrenderについては、「【Rails入門説明書】redirect_toについて解説」を参照してください)
renderを使った場合の動きも確認しておきましょう。
コントローラを以下のように修正してください。
(app/controllers/items_controller.rb)
:
def create
@item = Item.new(item_params)
respond_to do |format|
if @item.save
flash[:complete] = “created item!” # (1)
# format.html { redirect_to @item, notice: ‘Item was successfully created.’ } # コメントアウト
format.html { render :show, status: :created, location: @item } # 追加
format.json { render :show, status: :created, location: @item }
else
format.html { render :new }
format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
:
これで、登録後の画面表示が、redirect_toではなくrenderでの再表示になりました。
この状態で1件登録しても、今まで通りflashメッセージが表示されます。
では、先ほどと同じように「Back」をクリックしてみましょう。
一覧画面へ遷移しましたが、flashメッセージが表示されたままになっています。念のため、F5キーで再表示してみると、メッセージは消えます。
じつは、renderを使用する表示の変更は、「ページ遷移」ではありません。あくまでも表示を変更しているだけです。そのため、「Back」クリックで、初めて1回目のページ遷移が行われたため、一覧表示画面でメッセージが表示されたわけです。
renderメソッドを使うシーンでflashメソッドを使用する場合、この点に注意してプログラムを作らなければいけません。
もし、renderメソッドを使う表示の切り替えで、flashメッセージを消したい場合は、次のようにメッセージを登録しましょう。
flash.now[キー] = メッセージ
こうすることで、flashメッセージの寿命は、「そのページだけ」になりますので、renderメソッドで表示を切り替えたときに表示され、その後のページ切り替えでメッセージが消えます。
なお、リダイレクトするシーンでflash.nowを使用すると、メッセージが表示されませんので、注意してください。
寿命を延ばしたい場合
もし、メッセージの寿命を延ばしたい場合は、次の1文を追加することで、ページ遷移1回分、寿命を延ばすことができます。
flash.keep[キー]
先ほど行ったコントローラの修正(renderでの画面遷移)を元に戻して、かつ、flash.keepの一文をshowメソッドに追加してください。
(app/controllers/items_controller.rb)
:
def show
flash.keep[:complete]
end
:
def create
@item = Item.new(item_params)
respond_to do |format|
if @item.save
flash[:complete] = “created item!” # (1)
format.html { redirect_to @item, notice: ‘Item was successfully created.’ } # 元に戻す
# format.html { render :show, status: :created, location: @item } # コメントアウト
format.json { render :show, status: :created, location: @item }
else
format.html { render :new }
format.json { render json: @item.errors, status: :unprocessable_entity }
end
end
end
:
動作確認してみれば、先ほどのrenderメソッドの場合と同じく、詳細画面と一覧画面でメッセージが表示され、その後一覧画面でF5キーを押して再表示すると、メッセージは消えます。
これは、以下のような流れで、flashメッセージの寿命が、ページ遷移1回分延命された結果です。
メッセージの格納場所
なお、Webアプリケーションも利用しているインターネットの基本プロトコルであるHTMLは、ステートレスなプロトコルですので、ページ間でデータを保持することができません。
しかし、ここまで説明したflashメソッドは、メッセージを次のページで表示しているように見えます。
じつは、flashメソッドは、デフォルトでローカルPCにデータを保持させて、メッセージ表示を実現しているのです。
その保存先は、ブラウザのCookieです。そのため、Cookieが無効になっているブラウザでは、flashメッセージは表示されませんので、注意してください。
https://web-camp.io/magazine/archives/12481
メッセージにタグを含める
最後に、表示するメッセージにタグを含めて、装飾や改行などを行う方法を説明します。
特に何もしなければ、flashメッセージに含まれるHTMLタグは、無効になります。
(app/controllers/items_controller.rb)
:
def create
@item = Item.new(item_params)
respond_to do |format|
if @item.save
flash[:complete] = “created <br> item!” # 改行してみる
:
この改行を有効にするには、Viewファイルでhtml_safeメソッドを使用します。
(app/views/items/show.html.erb)
<%= flash[:complete].html_safe %> <!– (3) タグ有効 –>
<%= notice %>
:
改行だけではなく、すべてのHTMLタグが有効になりますので、リンクを組み入れることも可能です。
セキュリティリスクを意識しよう
html_safeメソッドは、脆弱性になる可能性があることは理解しておいてください。
それは、flashメソッドで登録するメッセージを、フォームから入力された文字列にしてしまった場合です。
その場合、悪意のあるユーザーがフォームにScriptタグなどを入力することで、任意のソフトウェアを実行させることなどが可能になってしまうのです。
そのため、もしflashメッセージにフォームからの入力データが含まれる場合は、必ずHTMLタグを無効化するようにしましょう。
なお、文字列のHTMLタグを故意に無効化するにはhメソッドを利用します。
(app/views/items/show.html.erb)
<%= h(flash[:complete]).html_safe %> <!– (4) 無効化タグは有効にできない –>
<%= notice %>
:
Railsアプリケーションを作成するときは、セキュリティリスクは常に意識しなければいけません。
“未経験”でもたった1ヶ月で営業からエンジニアとして転職!『WebCamp』受講者インタビュー
まとめ
今回は、flashメソッドについて、解説しました。
Webアプリケーションを操作しているとき、アクセス中や何らかの登録するなどのタイミングでメッセージが表示されているかどうかだけで、ユーザーへ与える影響は大きく変わります。
flashメソッドは、簡単にメッセージを表示させることができるメソッドですので、積極的に活用して、ユーザーに状況を知らせることで、不安なくサービスを使ってもらうことができるのです。
ただし、flashメソッドはその使い方の簡単さから比較して、メッセージの寿命や表示するタイミングについては、少し難しく感じるかもしれません。しっかりと復習して、適切なメッセージが表示できるようにしていただければと思います。
メッセージ1つについても、ユーザーの使いやすさや印象を考慮して行うことができれば、中級プログラマーへまた1つ近づいたことになるでしょう。
・flashメソッドは、簡単にメッセージを表示することができる
・flashメソッドで登録したメッセージの寿命は、ページ遷移1回のみ
・flashメソッドで登録したメッセージは再表示では消えないため、renderを使用する場合はflash.nowを使う
・flash.keepメソッドで、メッセージ表示期間を1ページ遷移の分だけ伸ばせる
・メッセージに含まれるhtmlタグを無効にするのは「hメソッド」、有効にするのは「html_safeメソッド」を使う
・flashメソッドで表示される文字列は、セッションに格納されるため、デフォルトではCookieが有効でなければ使えない
・原則として、flashメソッドのメッセージは、1度表示されるとセッションから削除される
【インタビュー】1ヶ月でRubyをゼロから学び、Webエンジニアとして転職!
ブラジルから帰国し技術をつけようとRubyエンジニアを目指してWebCampでRubyを学び、見事Webエンジニアとして転職を果たした田中さんにお話を伺いました。
「Rubyの学習がしたい。基礎をしっかりと理解したい」
「転職のサポートがほしい」
と考えている方はぜひお読み下さい。
https://web-camp.io/magazine/archives/8535