何かの処理を行った時に(例えば以下のような)
・ユーザー登録に成功しました
・ログインしました
・口コミの投稿が成功しました
・写真を投稿しました
・本人確認に失敗しました
flashメッセージを使うことでメッセージを表示することができます。今日はflashメッセージの使い方と拡張・応用をしてみたのでそれを備忘録しています。
私は「写真を投稿しました」の時だけ「SNSボタンを表示してシェアしてみませんか?」みたいなこともやりたかったので、それも実装しました。
まずは簡単なflashメッセージの使い方
使い方は簡単です。コントローラー側で処理を行いそれにたいして(成功とか失敗とかの)flashメッセージを作成します。ビュー側でflashメッセージを表示します。
◆コントローラー側
flash[:success] = '写真を投稿しました' flash[:danger] = '写真の投稿に失敗しました' flash[:notice] = 'お知らせ' flash[:aiueo] = '文字列を入力'
こんな形です。flashメッセージはいわばハッシュなのでkeyとvalueを設定してあげる形です。
通常コントローラーからビューに変数を渡す時は変数の頭に@を付けるルールがあったと思いますが、flashメッセージには不要なようです。(railsドキュメント flashのリファレンス)
◆ビュー側
以下のようにしてメッセージを表示できます。
<%= flash[:success] %> <%= flash[:danger] %> <%= flash[:notice] %> <%= flash[:aiueo] %>
erbではhメソッドでHTMLエンコードも行うなら(例えば&は&とか<は<とか)
&amp;lt;%= h(flash[:success]) %&amp;gt; &amp;lt;%= h(flash[:danger]) %&amp;gt; &amp;lt;%= h(flash[:notice]) %&amp;gt; &amp;lt;%= h(flash[:aiueo]) %&amp;gt;
こんな形になります。
もしflashメッセージにHTMLタグを使うなら以下のように使えばよいでしょう。
◆コントローラー側
<br>タグで改行してみます。
flash[:aiueo] = '明日は&amp;lt;br&amp;gt;晴れるかなぁ'
◆ビュー側
html_safeメソッドを使ってHTMLタグをタグとして出力してくれます。
&amp;lt;%= flash[:aiueo].html_safe %&amp;gt;
flashメッセージが消えないときは
先程のリファレンスを見ると、flash.nowというメソッドがあるのでそれを活用すれば良いと思います。これで今のアクションにだけ適用されます。
コントローラー側で以下のように記述。
flash.now[:abc] = 'あべし'
逆にflashメッセージの有効期限を保持するのであれば、キーと値を設定した後に以下のようにメソッドを呼び出します。
flash.keep(:abc)
flashメッセージを外部ファイルでパーシャルにすると楽
パーシャルはどのビューにも共通する部分をまとめたファイルです。アンダーバーで始まるファイル名にします。
例えば、views/layouts/_flash_messages.html.erbというファイルを作ってそこにflashメッセージの表示部分を任せます。このやり方はテックアカデミーの教材で学びました。
外部ファイルの中身を以下のようにしています。
&amp;lt;% flash.each do |message_type, message| %&amp;gt; &amp;lt;div class=&amp;quot;alert alert-&amp;lt;%= message_type %&amp;gt;&amp;quot;&amp;gt; &amp;lt;%= message %&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;% end %&amp;gt;
これをビュー側でrenderメソッドを使って呼び出します。呼び出す時はディレクトリ/アンダーバーを消したファイル名(.html.erbも書かない)とします。
&amp;lt;%= render 'layouts/flash_messages' %&amp;gt;
flashメッセージのテクニック
もしcssでbootstrapによるデザインを使っているなら、flashメッセージのハッシュのkeyには:successや:infoや:dangerや:warningを使うことをおすすめします。(bootstrapじゃなくて自作のcssでも応用すれば良いと思います。)
bootstrapには以下の4つのcssのclassがありまして。
&amp;lt;div class=&amp;quot;alert alert-success&amp;quot;&amp;gt;成功時のメッセージカラーは緑&amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;alert alert-info&amp;quot;&amp;gt;通知用のメッセージカラーは青&amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;alert alert-warning&amp;quot;&amp;gt;警告用のメッセージカラーは黄色&amp;lt;/div&amp;gt; &amp;lt;div class=&amp;quot;alert alert-danger&amp;quot;&amp;gt;危険用のメッセージカラーは赤色&amp;lt;/div&amp;gt;
それぞれ以下のようなイメージでメッセージ表示用の吹き出しが出ます。これを活用しているのです。
flashメッセージの表示部分のここ↓ですね。
&amp;lt;% flash.each do |message_type, message| %&amp;gt; &amp;lt;div class=&amp;quot;alert alert-&amp;lt;%= message_type %&amp;gt;&amp;quot;&amp;gt;
flashメッセージのハッシュのkeyはflashのeach doで、message_typeで取り出してるのでbootstrapのクラス名に合わせることで、自動的に吹き出しの色を指定してるだけなんですが。
そして以下の部分でコントローラー側で設定したメッセージを表示します。
&amp;lt;%= message %&amp;gt;
成功したときにSNSボタンを表示させる
これは私自身が運営するWEBアプリで、そういう仕様にしたいと思いまして。
ユーザーによる投稿処理が成功したら、その画面でさらにSNS(FBやTwitter)にシェアをしてもらえたらな、という思いです。写真投稿に成功したときだけこのSNSボタンを表示させます。(SNSボタンを表示する方法に関しては前の記事に書いてあります。→【Rails】自作のSNSボタンを貼り付ける方法)
特に難しいことはなくて。
コントローラー側では以下のように記述。
if @photo.save #ここで写真を保存 flash[:photosuccess] = '写真を投稿しました!' else flash[:danger] = '写真の投稿に失敗しました' end redirect_to @shop
ビュー側(shops/show.html.erb)では以下のように記述。renderでflash_messagesを呼び出してるだけです。
&amp;lt;%= render 'layouts/flash_messages' %&amp;gt;
パーシャル(layouts/flash_messages.html.erb)では以下のように記述。
&amp;lt;% flash.each do |message_type, message| %&amp;gt; &amp;lt;% if flash[:photosuccess] %&amp;gt; &amp;lt;div class=&amp;quot;alert alert-success&amp;quot;&amp;gt; &amp;lt;%= message %&amp;gt; &amp;lt;p&amp;gt;是非SNSでも当サイトをシェアしてください。&amp;lt;/p&amp;gt; &amp;lt;%= render 'layouts/snsbutton' %&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;% else %&amp;gt; &amp;lt;div class=&amp;quot;alert alert-&amp;lt;%= message_type %&amp;gt;&amp;quot;&amp;gt; &amp;lt;%= message %&amp;gt; &amp;lt;/div&amp;gt; &amp;lt;% end %&amp;gt; &amp;lt;% end %&amp;gt;
これは3行目でflash[:photosuccess]があれば、「是非SNSでも当サイトをシェアしてください。」を表示して、なおかつ次の行でrenderメソッドで外部ファイルの_snsbutton.html.erbを表示しています。(この_snsbutton.html.erbにはSNSボタンが記述されています)
ということで投稿をしてもらった時だけ以下のようなSNSへのシェアを促すflashメッセージを出すようにしました。