Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rails 4 flash messages using Twitter Bootstrap(bootstrap-sass: https://github.com/thomas-mcdonald/bootstrap-sass). An improved version of https://gist.github.com/roberto/3344628
// layout file
<body>
<div class="container">
<%= flash_messages %>
<%= yield %>
</div><!-- /container -->
</body>
module ApplicationHelper
def bootstrap_class_for flash_type
{ success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }[flash_type] || flash_type.to_s
end
def flash_messages(opts = {})
flash.each do |msg_type, message|
concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do
concat content_tag(:button, 'x', class: "close", data: { dismiss: 'alert' })
concat message
end)
end
nil
end
end
@deploylinux

This comment has been minimized.

Copy link

@deploylinux deploylinux commented Dec 16, 2013

This actually worked best of all the suggested display methods for flash/alert messages in bootstrap 3 that I've looked at, however I did have to remove your 'yield' line .

@suryart

This comment has been minimized.

Copy link
Owner Author

@suryart suryart commented Dec 20, 2013

Layout file was just an example usage of the helper method.

Actually all you need is this line:

<%= flash_messages %>

to show the flash message wherever you need in your application.

@superbilk

This comment has been minimized.

Copy link

@superbilk superbilk commented Feb 22, 2014

I had to change flash_type .to_sym to get it working:

def bootstrap_class_for flash_type
    { success: "alert-success", error: "alert-error", alert: "alert-warning", notice: "alert-info" }[flash_type.to_sym] || flash_type.to_s
end
@AhmedNadar

This comment has been minimized.

Copy link

@AhmedNadar AhmedNadar commented Feb 24, 2014

Within my create action, i'm using redirect with a message:
=> redirect_to root_path, success: "Signed up successfully!"

There are 2 classes are not woking with me, 'success:' and 'error:', they are not showing their styled message. I don't know why??

@fernandokosh

This comment has been minimized.

Copy link

@fernandokosh fernandokosh commented Feb 26, 2014

Works fine for Rails 4.
Thanks

@pagedegeek

This comment has been minimized.

Copy link

@pagedegeek pagedegeek commented Apr 2, 2014

Also, you can use Hash#fetch

module ApplicationHelper

  BOOTSTRAP_FLASH_MSG = {
    success: 'alert-success',
    error: 'alert-error',
    alert: 'alert-block',
    notice: 'alert-info'
  }

  def bootstrap_class_for(flash_type)
    BOOTSTRAP_FLASH_MSG.fetch(flash_type, flash_type.to_s)
  end

end
@mamedov

This comment has been minimized.

Copy link

@mamedov mamedov commented Apr 2, 2014

Also I suggest to use '×'.html_safe instead of 'x' :) Will be more pretty

@mariozig

This comment has been minimized.

Copy link

@mariozig mariozig commented Apr 6, 2014

@pagedegeek
Nice use of Hash%fetch

@suryart

This comment has been minimized.

Copy link
Owner Author

@suryart suryart commented Apr 10, 2014

@AhmedNadar Check with the bootstrap class, it may have some different naming I guess.

@sovetnik

This comment has been minimized.

Copy link

@sovetnik sovetnik commented May 30, 2014

Can you help me add glyphicon inside you (awesome)version of flash?
In old version (based on partial), it can be like this:

application_helper.rb

  def bootstrap_icon_for flash_type
    { success: "ok-circle", error: "remove-circle", alert: "warning-sign", notice: "exclamation-sign" }[flash_type] || "question-sign"
  end

in flash_partial.erb:

<% flash.each do |type, message| %>
  <div class="alert <%= bootstrap_class_for(type) %> fade in">
    <button class="close" data-dismiss="alert"><i class="glyphicon glyphicon-remove-circle"></i></button>
    <i class="glyphicon glyphicon-<%= bootstrap_icon_for(type) %>"></i> <%= message %>
  </div>
<% end %>
@suryart

This comment has been minimized.

Copy link
Owner Author

@suryart suryart commented Jun 28, 2014

It should be:

def flash_messages(opts = {})
  flash.each do |msg_type, message|
    concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do 
            concat content_tag(:button, 'x', class: "close", data: { dismiss: 'alert' })
            concat content_tag(:i, nil, class: "glyphicon glyphicon-#{bootstrap_icon_for(type)}")
            concat message 
          end)
  end
  nil
end
@melnikaite

This comment has been minimized.

Copy link

@melnikaite melnikaite commented Oct 29, 2014

rails 4.1 with bootstrap 3

module ApplicationHelper
  def bootstrap_class_for flash_type
    { success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }[flash_type.to_sym] || flash_type.to_s
  end

  def flash_messages(opts = {})
    flash.each do |msg_type, message|
      concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} alert-dismissible", role: 'alert') do
        concat(content_tag(:button, class: 'close', data: { dismiss: 'alert' }) do
          concat content_tag(:span, '&times;'.html_safe, 'aria-hidden' => true)
          concat content_tag(:span, 'Close', class: 'sr-only')
        end)
        concat message
      end)
    end
    nil
  end
end
@doobee46

This comment has been minimized.

Copy link

@doobee46 doobee46 commented Dec 21, 2014

thanks , will put in good use

@cpshivhare

This comment has been minimized.

Copy link

@cpshivhare cpshivhare commented Feb 7, 2015

thanks

@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Mar 2, 2015

thanks, works greate !

@codeminator

This comment has been minimized.

Copy link

@codeminator codeminator commented Apr 26, 2015

+1 for superbilk .. i had to use to_sym for flash_type

@MrJadaml

This comment has been minimized.

Copy link

@MrJadaml MrJadaml commented May 15, 2015

Added clearing of flash messages after initial page view, and also had to change the bootstrap_class_for method to [flash_type.to_sym]

 def bootstrap_class_for flash_type
    { success: 'alert-success', error: 'alert-danger', warning: 'alert-warning'}[flash_type.to_sym]
 end

def flash_messages(opts = {})
    flash.each do |msg_type, message|
      concat(content_tag(:div, message, class: "text-center alert #{bootstrap_class_for(msg_type)} fade in") do
        concat content_tag(:button, 'x'.html_safe, class: 'close', data: {dismiss: 'alert'})
        concat message
      end)
      flash.clear
    end
    nil
  end
@Startouf

This comment has been minimized.

Copy link

@Startouf Startouf commented Jun 18, 2015

A version that handles array of flashes (eg flash[:notice] = ["something happened", "something else happened"]), that also lets you define custom flash types (eg flash[:todo]).
Works on Rails 4.2, Bootstrap 3

Somewhere in application.html.erb

<% flash.each do |type, content| %>
    <% if content.respond_to?('each') 
        content.each do |item| %>
            <%= render 'layouts/alert', 
                type: type,
                content: item %>
        <% end %>
    <% else %>
        <%= render 'layouts/alert', 
                type: type,
                content: content %>
    <% end %>

<% end %>

_layouts/alert.html.erb

<div class="alert 
    <%= 
    case type.to_sym 
    when :alert, :danger, :error, :validation_errors
        'alert-danger'
    when :warning, :todo
        'alert-warning'
    when :notice, :success
        'alert-success'
    else 
        'alert-info'
    end
    %>
     alert-dismissible" role="alert">
    <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
    <%= content %>
</div>
@hoang1417

This comment has been minimized.

Copy link

@hoang1417 hoang1417 commented Jun 29, 2015

thanks, it rocks

@aruprakshit

This comment has been minimized.

Copy link

@aruprakshit aruprakshit commented Jul 1, 2015

very helpful gist it is.

@ram619prasad

This comment has been minimized.

Copy link

@ram619prasad ram619prasad commented Aug 12, 2015

How to display the flash message at a specific position like flash coming from right side, rather than at the top. Please do help :)

@ahmadhasankhan

This comment has been minimized.

Copy link

@ahmadhasankhan ahmadhasankhan commented Aug 20, 2015

application.html.erb

<% if notice || alert %>
    <div class="alert <%= notice ? "alert-info" : "" %><%= alert ? "alert-danger" : "" %> alert-dismissible" role="alert">
        <button type="button" class="close" data-dismiss="alert">
            <span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
        <div >
            <% if notice %>
                <%= notice %>
            <% elsif alert %>
                <%= alert %>
            <% end %>
        </div>
    </div>
<% end %>

application.js

$(function() {
    var flashCallback;
    flashCallback = function() {
        return $(".alert").fadeOut();
    };
    $(".alert").bind('click', (function(_this) {
        return function(ev) {
            return $(".alert").fadeOut();
        };
    })(this));
    return setTimeout(flashCallback, 2000);
});
@mammothbane

This comment has been minimized.

Copy link

@mammothbane mammothbane commented Aug 21, 2015

i ran into an issue with hash access, so my bootstrap_class_for looks like this:

def bootstrap_class_for flash_type
  hash = HashWithIndifferentAccess.new({ success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" })
  hash[flash_type] || flash_type.to_s
end

i also wanted flash_messages to be embeddable in a location of my choice (i.e. return the actual HTML for the flashes and not render them at the top of the page), so mine looks like this:

def flash_messages(opts = {})
  html_all = ""
  flash.each do |msg_type, message|
    html = <<-HTML
    <div class="alert #{bootstrap_class_for(msg_type)} alert-dismissable"><button type="button" class="close"
    data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      #{message}
    </div>
    HTML
    html_all += html
  end
  html_all.html_safe
end
@EvgeniyRRU

This comment has been minimized.

Copy link

@EvgeniyRRU EvgeniyRRU commented Aug 31, 2015

And did you know, how to test it via Rspec?

@jcmorrow

This comment has been minimized.

Copy link

@jcmorrow jcmorrow commented Sep 2, 2015

Can someone explain to me why I have to use (in HAML):

-flash_messages

instead of

=flash_messages

to get the flash messages to appear where the helper is called rather than automatically being the first element on the page?

@ram619prasad I think this might address your questions also.

@foton

This comment has been minimized.

Copy link

@foton foton commented Dec 29, 2015

Thank s for gist, I used it in Material Design Lite. But there are no "alerts" (yet?) sou basically I borrow CSS from Bootstrap.

@liamwhite

This comment has been minimized.

Copy link

@liamwhite liamwhite commented Jan 4, 2016

@jcmorrow Because the helper concats the flash to the current buffer instead of returning it as a string.

@irbux

This comment has been minimized.

Copy link

@irbux irbux commented Jan 9, 2016

Thanks suryart and melnikaite, all is works good for me. (Rails 4.1)

@eltonsantos

This comment has been minimized.

Copy link

@eltonsantos eltonsantos commented Jan 12, 2016

It's work in rails 4.2.5 and ruby 2.3.0. Thanks!!

I used this way:

def message
    html_message = ''
    [:success, :info, :error, :notice].each { |tipo|
      if flash[tipo]
        html_message << "<div class='alert-message alert #{"alert-#{tipo}" if tipo != :alert} alert-block fade in'>"
        html_message << '<button type="button" class="close" data-dismiss="alert">&times;</button>'
        html_message << flash[tipo]
        html_message << '</div>'
      end
    }
    raw(html_message)
  end
@ghost

This comment has been minimized.

Copy link

@ghost ghost commented Feb 18, 2016

Why "success" and "error" aren't show?

@elvynmejia

This comment has been minimized.

Copy link

@elvynmejia elvynmejia commented Feb 23, 2016

How can I use <%= flash_messages %> inside an each loop?

@olenberg

This comment has been minimized.

Copy link

@olenberg olenberg commented Mar 9, 2016

Thank's for gist! It eases my life)))

@yeahmx91

This comment has been minimized.

Copy link

@yeahmx91 yeahmx91 commented May 20, 2016

It took me a while to get this working because its my second day with ruby and rails.

I have rails 4.2.6 with bootstrap-sass 3.3.6 (thanks to Bandon Conway) and it worked with the melnikaite code.

Thank you guys! I'll commit asap.
So pretty

@rom5jp

This comment has been minimized.

Copy link

@rom5jp rom5jp commented Jun 16, 2016

It works perfectly! Thank you so much!

@twnaing

This comment has been minimized.

Copy link

@twnaing twnaing commented Jun 28, 2016

@unknown, according to the following documentation

There are two special accessors for the commonly used flash names alert and notice as well as a general purpose flash bucket.

you have to use the following

redirect_to @resource, alert: 'message'
redirect_to @resource, notice: 'message'
redirect_to @resource, flash: { success: 'message' }
redirect_to @resource, flash: { error: 'message' }
@gunterja

This comment has been minimized.

Copy link

@gunterja gunterja commented Aug 11, 2016

@AhmedNadar

Try extending the bootstrap classes in application.scss like this:

/* Extending the Bootrstrap classes to cover all possible Flash types */

.alert-alert {
  @extend .alert-danger;
}

.alert-notice {
  @extend .alert-warning;
}
@hendricius

This comment has been minimized.

Copy link

@hendricius hendricius commented Jan 18, 2017

Apparently in Rails 5 the flash messages each have a string. I just stringified the hash:

  def bootstrap_class_for flash_type
    { success: "alert-success", error: "alert-danger", alert: "alert-warning", notice: "alert-info" }.stringify_keys[flash_type.to_s] || flash_type.to_s
  end

  def flash_messages(opts = {})
    flash.each do |msg_type, message|
      concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} fade in") do 
              concat content_tag(:button, 'x', class: "close", data: { dismiss: 'alert' })
              concat message 
            end)
    end
    nil
  end

@trendwithin

This comment has been minimized.

Copy link

@trendwithin trendwithin commented Apr 21, 2017

This has always worked like a charm for me and I habitually copied and pasted this in my projects, so perhaps I can save someone else a headache. Currently using 'bootstrap', '~> 4.0.0.alpha6' and fade in is now fade show.

@naterexw

This comment has been minimized.

Copy link

@naterexw naterexw commented Aug 3, 2017

To add font-awesome icons in Rails 5, Bootstrap 4 beta 2:

  def flash_messages(opts = {})
    flash.each do |msg_type, message|
      concat(content_tag(:div, message, class: "alert #{bootstrap_class_for(msg_type)} alert-dismissible fade show", role: 'alert') do
        concat(content_tag(:button, class: 'close', data: { dismiss: 'alert' }, 'aria-label' => "Close" ) do
          concat content_tag(:span, '&times;'.html_safe, 'aria-hidden' => true)
        end)
        case
        when bootstrap_class_for(msg_type) == "alert-success"
          concat content_tag(:span, '<i class="fa fa-check-circle"></i>'.html_safe, 'aria-hidden' => true)
        when bootstrap_class_for(msg_type) == ("alert-danger" || "alert-warning")
          concat content_tag(:span, '<i class="fa fa-times-circle"></i>'.html_safe, 'aria-hidden' => true)
        else
          concat content_tag(:span, '<i class="fa fa-info-circle"></i>'.html_safe, 'aria-hidden' => true)
        end
        concat " " + message
        concat "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".html_safe
      end)
    end
    nil
  end
@sasankjonna

This comment has been minimized.

Copy link

@sasankjonna sasankjonna commented Sep 6, 2017

Is there a preview of how it works?

@ryanoff

This comment has been minimized.

Copy link

@ryanoff ryanoff commented Jan 25, 2018

@naterexw, this works great. How about having the error message fade out to close after 4 seconds?

@davegson

This comment has been minimized.

Copy link

@davegson davegson commented May 10, 2018

A very basic and simple solution for Bootstrap 4:

application_helper.rb

module ApplicationHelper
  def bootstrap_class_for(flash_type)
    {
      success: 'alert-success',
      error: 'alert-danger',
      alert: 'alert-warning',
      notice: 'alert-primary'
    }[flash_type.to_sym] || flash_type.to_s
  end
end

application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <!-- . -->
    <!-- . -->
  </head>
  <body>
    <div class='container'>
      <% flash.each do |type, content| %>
        <%= render 'partials/flash', type: type, content: content %>
      <% end %>

      <%= yield %>
    </div>
  </body>
</html>

_app/views/partials/flash.html.erb

<div class="alert <%= bootstrap_class_for(type) %> alert-dismissible fade show" role="alert">
  <button type="button" class="close" data-dismiss="alert" data-aria-label="Close">
    <span aria-hidden="true">&times;</span>
  </button>
  <div class="text">
    <%= content %>
  </div>
</div>
@superbilk

This comment has been minimized.

Copy link

@superbilk superbilk commented Jul 15, 2018

Small typo with https://gist.github.com/suryart/7418454#gistcomment-2584737
correct file name is app/views/partials/_flash.html.erb (mind the underscore)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.