9

Hello I am new to ruby on rails and I am struggling to understand I18n's flash messages. I am using devise, rails 4, and twitter bootstrap.I understand that devise only uses flash[:notice] and flash[:alert].

I am able to get flash messages working for my user model with signing in and logging out. However I cannot get the flash error for signup or forgot password to display properly. It looks like the default error message.

I've looked at bunch of questions related to this and Im confused on the way to go about displaying all flash messages (errors, successes, notifications) with pretty css.

Perhaps the answer is already in this article right under my nose? rails - Devise - Handling - devise_error_messages

Currently my flash messages are based on How to define Flash Notifications with Twitter Bootstrap Rails gem

Here is my example:
within 'app/views/layouts/application.html.erb'

<%= render 'layouts/messages' %>

'app/views/layouts/_messages.html.erb'

<% flash.each do |name, msg| %>
  <% if msg.is_a?(String) %>
    <div class="alert alert-<%= name == :notice ? "success" : "error" %>">
      <a class="close" data-dismiss="alert">&#215;</a>
      <%= content_tag :div, msg, :id => "flash_#{name}" %>
    </div>
  <% end %>
<% end %>

How do I display all flash messages (errors, successes, notifications) using my custom css?

Update: This post displays a correct version of what I am trying to do. The problem I have is that the styling does not look the same. I believe it is because of the html tag.

html = <<-HTML
 <div class="alert alert-error alert-block"> <button type="button"
  class="close" data-dismiss="alert">x</button>
  <h4>#{sentence}</h4>
  #{messages}
 </div>
HTML

Any idea how I can have the same styling for the alerts? or what tags to use in the css?

signup error

You can see the difference between the sign up^^ and sign in (below) pages.

signin error

Update2

I've made a new post on what my problem is- which can be found here.
Utku
  • 2,025
  • 22
  • 42
Daniel
  • 2,950
  • 2
  • 25
  • 45
  • Have you try this question? http://stackoverflow.com/questions/8705590/custom-classes-and-formatting-on-flash-messages-for-twitter-bootstrap-defaults?rq=1. Your question is about using your css or I18n? – ksugiarto Nov 27 '13 at 05:25
  • I actually just saw that, and just tried it. I could not however get it to work. I still have the same results. – Daniel Nov 27 '13 at 05:50
  • I followed the lead on this and it came pretty close to working. http://stackoverflow.com/questions/20171539/how-to-apply-customized-bootstrap-messages-errors-to-devise/20235279#20235279 I have colors for everything but I am unsure how to change colors for each alert – Daniel Nov 27 '13 at 07:04
  • My question is about I18n and css. I am not sure how to get it to display correctly. I want all the error fields to be red, and any successes + good things to be green. – Daniel Nov 27 '13 at 18:48

6 Answers6

13

I made a wiki page within the devise wiki on github for How To: Integrate I18n Flash Messages with Devise and Bootstrap

Flash Messages For the Site

First we will make a rendered view to make the code concise. Within "app/views/layouts/application.html.erb" I added <%= render 'layouts/messages' %>.

My file looks like:

<body>
  <%= render 'layouts/header' %>
  <div class="container">
    <%= render 'layouts/messages' %>
    <%= yield %>
    <%= render 'layouts/footer' %>
  </div>
</body>

Next we have to make the messages file. Make a new file in "app/views/layouts/_messages.html.erb" and add:

<% flash.each do |key, value| %>
  <div class="alert alert-<%= key %>">
    <a href="#" data-dismiss="alert" class="close">×</a>
      <ul>
        <li>
          <%= value %>
        </li>
      </ul>
  </div>
<% end %>

This will give us flash messages for the entire site.

Flash Messages For Devise

For devise you need to override the way devise handles flash messages. Create a file called devise_helper in "app/helpers/devise_helper.rb".

Inside the file you have to create a method called devise_error_messages!, which is the name of the file that tells devise how to handle flash messages.

module DeviseHelper
  def devise_error_messages!
    return '' if resource.errors.empty?

    messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
    html = <<-HTML
    <div class="alert alert-error alert-block"> <button type="button"
    class="close" data-dismiss="alert">x</button>
      #{messages}
    </div>
    HTML

    html.html_safe
  end
end

Next in your devise views you will have to define where you want the error messages to appear. You will need to enter <%= devise_error_messages! %> within the devise pages. An example is entering this within "app/views/devise/registrations/.new.html.erb" (The sign up page)

It should already be within the file, but you can move the code around to customize where it is shown.

CSS For Flash Messages

If you do not want to use the odd blue and yellow alerts that come default, I have set error and alert to have the same colorand success and notice to have the same color. I am using red for errors and alerts, and green for success and notice.

Within my "app/assets/stylesheets/custom.css.scss" I have:

/*flash*/
.alert-error {
    background-color: #f2dede;
    border-color: #eed3d7;
    color: #b94a48;
    text-align: left;
 }

.alert-alert {
    background-color: #f2dede;
    border-color: #eed3d7;
    color: #b94a48;
    text-align: left;
 }

.alert-success {
    background-color: #dff0d8;
    border-color: #d6e9c6;
    color: #468847;
    text-align: left;
 }

.alert-notice {
    background-color: #dff0d8;
    border-color: #d6e9c6;
    color: #468847;
    text-align: left;
 }
Daniel
  • 2,950
  • 2
  • 25
  • 45
  • While this may theoretically answer the question, [it would be preferable](http://meta.stackexchange.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Bill the Lizard Dec 22 '13 at 13:25
9

Here's my 2 cents. Using a case statement to check if the flash names are the older syntax alertor notice and change them to success or danger if they are and leave everything else alone.

<div class="container">
  <% flash.each do |name, msg| %>
    <% if msg.is_a?(String) %>
      <div class="alert alert-<%= flash_class_name(name) %>" role="alert">
        <button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span>
        <span class="sr-only">Close</span>
        </button>
        <%= content_tag :div, msg, :id => "flash_#{name}" %>
      </div>
    <% end %>
  <% end %>
</div>

and a helper method

def flash_class_name(name)
    case name
    when 'notice' then 'success'
    when 'alert'  then 'danger'
    else name
    end
end
loubotics
  • 171
  • 2
  • 5
5

If you use Sass in your app, you can extend BS classes alert-info and alert-danger with Devise's alert-notice and alert-alert respectively, in a way like this:

.alert-notice {
  @extend .alert-info
}

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

By adding this to your *.scss, Devise flash messages will inherit the styles of BS info and danger alerts.

http://sass-lang.com/guide (Extend/Inheritance section)

chaimann
  • 193
  • 1
  • 8
2

The simplest solution I've found is to use a common partial for all flash messages while checking for :notice and :alertto replace with the necessary bootstrap class.

So make /views/shared/_alerts.html.erb like this -

<% flash.each do |message_type, message| %>
<div class="alert alert-<%= flash_class_name(message_type) %> alert-dismissable">
    <span><%= message %></span>
    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
        <span aria-hidden="true">&times;</span>
    </button>
  </div>
<% end %>

Add a helper method (I've added it to the application helper) like this -

def flash_class_name(name)
    case name
    when "notice" then "success"
    when "alert"  then "danger"
    else name
    end
end

Include _alerts.html.erb in the application layout (or the parent layout for your application).

That's it!

nphadke
  • 502
  • 5
  • 8
1

With Boostrap 3.1, for me works in this way:

 html = <<-HTML
    <div class="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>
      <strong>#{sentence}</strong>
      <ul>
        #{messages}
      </ul>
    </div>

HTML

matiasmasca
  • 605
  • 8
  • 14
0

Actually bootstrap provide some alert class, please try for class with alert alert-warning for yellow warning, alert alert-success for green warning, alert alert-danger for red warning.

And for the I18n you can just directly using that just like on the view.

Also if you want to forcing using your class rather than bootstrap class, you can using !important at your class for example:

.alert
{
  background: #f3f3f3 !important;
  color: black !important;
}

Please correct me if I'm wrong.

ksugiarto
  • 940
  • 1
  • 17
  • 40
  • Thanks I see what you mean with forcing it on the bootstrap class. I want to keep the alert alert-danger and alert alert success that I18n provides. However if you look at my pictures you can see that the alert alert-danger provided me with two different styled alert boxes. I want Both of the boxes to look the same. (one red line goes across the page, other doesn't go all the way across) – Daniel Nov 28 '13 at 04:13
  • Hmm. I think both box has same style, that different is because of the sender right, the upper was coming from Rails validation, when bottom one was coming from Devise message. Sorry I can't give you more solution. But for the `I18n` fro the Devise you can change it by your own on `config/locales/devise.en.yml`. Sorry if still not so understand the case. – ksugiarto Nov 28 '13 at 09:55
  • Thank you, your answer helped me understand how the css works with I18n, but here is another post I made which states my problem clearer. My problem is with devise I believe. – Daniel Nov 28 '13 at 17:34