基本

Ruby on Railsのフラッシュメッセージでリダイレクト先にデータを渡す

Ruby on Railsのフラッシュメッセージは、リダイレクト先のページに一時的なデータ(通知メッセージなど)を渡すための仕組みです。通常のインスタンス変数はリダイレクト時にリセットされるため、成功メッセージやエラーメッセージをリダイレクト先に表示するにはフラッシュを使う必要があります。この記事では、フラッシュメッセージの使い方と活用パターンを解説します。

基本的な使い方

flashハッシュにキーと値を設定し、redirect_toでリダイレクトすると、リダイレクト先のページでそのデータを参照できます。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      flash[:notice] = "投稿を作成しました"
      redirect_to @post
    else
      render :new
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    flash[:alert] = "投稿を削除しました"
    redirect_to posts_path
  end
end

フラッシュに設定したデータは次のリクエストで1回だけ参照でき、その後は自動的に消去されます。この特性により、ページをリロードするとメッセージは消えます。

redirect_toとの省略記法

redirect_tonoticealertオプションを使うと、フラッシュの設定とリダイレクトを1行で書けます。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: "投稿を作成しました"
    else
      render :new
    end
  end

  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    redirect_to posts_path, alert: "投稿を削除しました"
  end
end

この省略記法はflash[:notice] = "..."redirect_toを組み合わせたものと同じ動作です。コードがすっきりするため、こちらの書き方が推奨されます。

ビューでのフラッシュ表示

フラッシュメッセージをビューに表示するには、レイアウトファイルに以下のようなコードを追加します。

app/views/layouts/application.html.erb
<body>
  <% flash.each do |type, message| %>
    <div class="alert alert-<%= type %>">
      <%= message %>
    </div>
  <% end %>

  <%= yield %>
</body>

flash.eachでフラッシュに格納されたすべてのメッセージを表示しています。typeにはnoticealertなどのキーが入るため、CSSクラスに利用してスタイルを変えることができます。

flash.nowの使い方

flash.nowは、リダイレクトせずに現在のリクエスト内でフラッシュメッセージを表示する場合に使います。

app/controllers/posts_controller.rb
class PostsController < ApplicationController
  def create
    @post = Post.new(post_params)
    if @post.save
      redirect_to @post, notice: "投稿を作成しました"
    else
      flash.now[:alert] = "入力内容にエラーがあります"
      render :new
      # renderなのでflash.nowを使う
    end
  end
end

renderはリダイレクトと異なり新しいリクエストを発生させないため、通常のflashを使うと次のリクエストまでメッセージが残ってしまいます。flash.nowを使えば現在のリクエストでのみメッセージが表示されます。

ポイント

redirect_toのときはflashを、renderのときはflash.nowを使うと覚えましょう。間違えるとメッセージが表示されなかったり、余計なタイミングで表示されたりします。

カスタムフラッシュキー

noticealert以外にも、任意のキーでフラッシュを使えます。

Ruby
flash[:success] = "正常に完了しました"
flash[:warning] = "注意が必要です"
flash[:info] = "お知らせがあります"

ただし、redirect_toの省略記法(notice:alert:)が使えるのはnoticealertのみです。カスタムキーを使う場合は明示的にflash[:key] = valueと書く必要があります。

注意

フラッシュには文字列など簡潔なデータのみを保存しましょう。大きなオブジェクトや機密情報はフラッシュではなくセッションやデータベースに保存してください。フラッシュデータはクッキーを介してやり取りされるため、サイズと安全性に制約があります。

まとめ

  • flash[:key] = "メッセージ"でリダイレクト先にデータを渡せる
  • redirect_to path, notice: "..."の省略記法が便利
  • フラッシュデータは次のリクエストで1回だけ参照され、自動的に消去される
  • redirect_toにはflashrenderにはflash.nowを使う
  • レイアウトでflash.eachを使ってすべてのメッセージを表示する
  • フラッシュには簡潔なデータのみを保存し、大きなデータは別の手段で管理する