DEV Community

Cover image for Flash Messages (notifications) in Rails Apps
Rails Designer
Rails Designer

Posted on • Originally published at railsdesigner.com

Flash Messages (notifications) in Rails Apps

This article was originally published at Rails Designer.


Flash has been a feature of Rails since the earliest version, and besides some refinements, the functionality stayed the same.

The flash feature is an easy way to pass temporary messages, like success messages or error notices, from controllers to views, it's stored in the user's session and immediately cleared out after display. Thus they’ll be gone by the time the next action is performed.

The most basic version, that's been around since the first version, looks like this:

# app/controllers/users_controller.rb
def create
  if @user.save
    flash[:notice] = "User Saved"
    redirect_to @user
    # or: redirect_to @user, notice: "User Saved"
  end
end
Enter fullscreen mode Exit fullscreen mode
<div id="flash">
  <% if flash[:notice] %>
    <div class="notice">
      <%= flash[:notice] %>
    </div>
  <⁠% end %>
</div>
Enter fullscreen mode Exit fullscreen mode

When to use flash message?

I've seen flash messages often been used incorrectly. So when should you show a flash message? When an action was successfully performed, examples:

  • saved a record;
  • started performing something in the background (eg. CSV export);
  • something finished performing in the background (eg. video exported);
  • record was created by someone/something else (eg. a new email arrived).

Flash messages should not be used to show form validation errors, examples are "Password is incorrect" or "Username is too short". Those are validation errors and should be displayed as close to form (field) as possible.

Using flash messages with Turbo (streams)

The example use of flash messages above work perfectly fine when you are doing a redirect in the controller's action. Still today, after almost 20 years. But today, you can also render something without redirecting the page, using turbo (streams).

The code needed is almost the same, but requires a bit more set up:

# app/controllers/users_controller.rb
def create
  if @user.save
    respond_to do |format|
      format.html { redirect_to @user, notice: "User Saved" }
      format.turbo_stream { flash.now[:notice] = "User Saved" }
    end
  else
    render :new
  end
end
Enter fullscreen mode Exit fullscreen mode
# app/views/users/create.turbo_stream.erb
<%= turbo_stream.replace "flash" do %>
  <div class="notice">
    <%= flash[:notice] %>
  </div>
<⁠% end %>
Enter fullscreen mode Exit fullscreen mode

Mind the differences:

  • instead of flash[:notice], flash.now[:notice] is needed. This is because there's no redirect happening. So the flash message needs to be available “now”;
  • the turbo_stream response is needed to tell what to do. In this case replace the #flash div with the the given HTML (there's probably more in that turbo-stream response).

Flash messages with Turbo Stream broadcasts

If a long-running task has finished in the background, or something else happened the user wants to know about, broadcasting flash messages is a great option.

# app/models/user.rb
after_create_commit -> {
  broadcast_replace_to(
    "flash_messages",
    target: "flash",
    partial: "shared/flash", locals: { flash: "User Saved" }
  )
}
Enter fullscreen mode Exit fullscreen mode
# app/views/shared/_flash.html.erb
<% if flash[:notice] %>
  <div class="notice">
    <%= flash[:notice] %>
  </div>
<⁠% end %>
Enter fullscreen mode Exit fullscreen mode
# app/views/layouts/application.html.erb
<%= turbo_stream_from("flash_messages")
Enter fullscreen mode Exit fullscreen mode

Here, after the user is created, a turbo-stream is broadcasted with the newly created flash-partial (app/views/shared/_flash.html.erb). Replacing the #flash div similar to how it's done in the controller's action.

This is a simplified version, as who sees flash messages and when might be a bit more complicated.

More advanced flash messages

Once you know you can use flash messages beyond just simple confirmation messages (“User Saved”, “Signed up Successfully”, and so on), you might want to explore more advanced flash messages.

Take a look at this example from Rails Designer's Notification Component:

Preview of an advanced notification in Rails

This can be done by passing more data to the flash message, like so:

flash[:alert] = {
  message: "Suspicious Login Attempt",
  description: "We've prevented a login from an unrecognized source.",
  primary_action: {title: "Review Activity", path: "#"},
  secondary_action: {title: "It's Me", path: "#"}
}
Enter fullscreen mode Exit fullscreen mode

In the flash partial (app/views/shared/_flash.html.erb) grab the data, like so:

# app/views/shared/_flash.html.erb
<% if flash[:notice] %>
  <div class="notice">
    <%= flash[:message] %>
    <%= flash[:description] %>
    <%# etc. %>
  </div>
<⁠% end %>
Enter fullscreen mode Exit fullscreen mode

That's the gist of adding more advanced flash messages. Of course it needs more HTML and CSS. For more examples and inspiration, check out the notifications I created for Rails Designer.

And that's all there's to flash messages in Rails. From really simple ones to quite advanced user-focused notifications that allow actions to them.

Top comments (0)