How can I pass an optional parameter to the flash message?
I'm using Twitter Bootstrap alert messages, and I want to add the ".alert-block" css class to the message, based on a parameter or something I set in the controller.
Thanks.
This is my solution:
flash[:success_block] = "<h4>Bla blah.</h4> <p>Blah blah.</p>"
<% flash.each do |name, msg| %>
<% block = true if name.to_s.split('_').last == 'block' %>
<% name = name.to_s.split('_').first if block %>
<div class="alert fade in alert-<%= name %> <%= 'alert-block' if block %>">
<a class="close" data-dismiss="alert">×</a>
<%= msg.html_safe %>
</div>
<% end %>
The best practice is to map the flash message on the different alert types that twitter bootstrap provides (ie flash[:info] to .alert-info, flash[:success to alert-success]...)
You can't pass parameters to flash variables, but you can access instance variables of a controller, or even methods by using helper_method from your views/layouts.
Related
How to I add an error with a line break? When I try adding \n it gets ignored, and when I try adding <br>, it just displays it.
Controller:
errors.add(:base, "This is the first line \n this is the second line")
View:
<% if message_form.errors.any? %>
<div class='row'>
<div class= 'col-md-12'>
<div id="error_explanation" >
<h5><%= pluralize(message_form.errors.count, "error") %> prohibited error prevented save:</h5>
<ul>
<% message_form.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
</div>
</div>
<% end %>
Probably you need to use <br> together with html_safe helper to mark that string as safe and skip all additional escaping.
However, you should take into account that if you mark as html_safe a string with user-provided inputs (or external inputs in general) you may be exposed to HTML injection or XSS attacks.
In case that is what you are trying to achieve, I would like to mention that you can associate more than one error to the same attribute, as explained in the Rails documentation.
I am trying to create a todo app that will allow the user to create lists and then "todo" items under each list. However, I want each user to only be able to see his or her lists. While I've been able to partially solve it using the current_user helper, the index page shows empty space where the other users lists are hidden.
Below please find the code for the index.html.erb page inside my todo_lists views.
<% #todo_lists.each do |todo_list| %>
<div class="index_row clearfix">
<% if todo_list.user == current_user %>
<h2 class="todo_list_title"><%= link_to todo_list.title, todo_list %></h2>
<p class="todo_list_sub_title"><%= todo_list.description %></p>
<p><%= todo_list.user.first_name %></p>
<% end %>
</div>
<% end %>
<div class="links">
<%= link_to "New Todo List", new_todo_list_path %>
</div>
Here's my repo on Github, in case you need to see more of the code: https://github.com/jramoscolon/todo
Is there a way to hide these empty spaces, as well as the non-matching todo items?
Given your current view code, you are indiscriminately emitting <div class="index_row clearfix"> elements, even when the todo_list.user does not match the current_user. Simply move the whole<div> outside the current_user check, like so:
<% #todo_lists.each do |todo_list| %>
<% if todo_list.user == current_user %>
<div class="index_row clearfix">
<h2 class="todo_list_title"><%= link_to todo_list.title, todo_list %></h2>
<p class="todo_list_sub_title"><%= todo_list.description %></p>
<p><%= todo_list.user.first_name %></p>
</div>
<% end %>
<% end %>
This way, all of those empty <div> elements aren't included on the page. This should clean up all that empty space.
If your index view is user specific than the instance variable you want should be user specific as well.
Instead of #todo_lists = ToDoList.all
Use the current_user.todo_lists functionality supplied by your has_many/belongs to
I'm not sure why this is happening, but when I submit a form successfully in my rails app it is adding a div class of an error to my successful flash message. I'm using this code for my flash messages:
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
</div>
<% end %>
That's exactly what Ryan Bates suggests doing in this rails cast:
http://railscasts.com/episodes/329-more-on-twitter-bootstrap?view=asciicast
What is wrong with that code? It works fine if I simply do this:
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name %>">
<a class="close" data-dismiss="alert">×</a>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
</div>
<% end %>
But that doesn't seem to be the right way to do this. I don't understand why the code suggested in the railscast doesn't work.
You may put a string 'notice' instead of a symbol :notice when you created the flash message in your controller. Try adding these lines in your application.html.haml to see what you get from your flash messages
- if Rails.env.development?
= debug(params)
= debug(flash) unless flash.empty?
As far as I remember, flash sometimes contain empty elements. Check if you have something in flash before iteration.
im using twitters bootstrap alert messages. in my application.html.erb I have...
<% flash.each do |key, value| %>
<div class="alert alert-<%=key%>">
<a class="close" data-dismiss="alert">×</a>
<%= value %>
</div>
<% end %>
normally when I want to do a flash message, I would write something like
flash[:success] = "Profile updated"
however im not sure how I can give the devise error messages a key and value pair. I looked into the devise.en.yml but can't seem to associate the message with a key ie :success, :error etc.
could someone help? thanks!
For anyone coming across this that does not know how to override the devise error messages with bootstrap.
Create file named:
/app/helpers/devise_helper.rb
Add the following code:
module DeviseHelper
def devise_error_messages!
return '' if resource.errors.empty?
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
sentence = I18n.t('errors.messages.not_saved',
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
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
html.html_safe
end
end
This is how i do it
<% flash.each do |key, value| %>
<div class="message">
<div class="alert-message <%= key %> fade in">
<a class="close" href="#">×</a>
<center><strong><%= value %></strong></center>
</div>
</div>
<% end %>
The simplest solution I've found is to use a common partial for all flash messages while checking for :notice and :alert to 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">×</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!
Thing is that devise_error_messages! by itself wraps the data into div with class='alert', so the form will have 2 nested divs with the same class. Pressing the x button will close nested div, leaving empty div styled as alert. To avoid this you can omit the div inside helper return value as following:
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
<button type="button" class="close" data-dismiss="alert">x</button>
#{messages}
HTML
html.html_safe
end
end
I'm using the Devise gem and I just would like to show a successful message when someone ask for a new password (if forgotten). Currently, when submitted, the button redirects to sign_in without any message.
Thank you
Rather than using the flash and trying to work out how Devise does it's thing (not for the faint-hearted) by extending its controllers, how about checking the referrer, and displaying a message in the view if it matches your 'remind me of my password' path?
In the view:
<% if request.env['HTTP_REFERER'] == "/give/me/a/new/password" %>
<h2>Your password stuff is all good now.</h2>
<% end %>
flash[:success] = "Something Something"
Devise rolls out it's own alert messages (and they can be edited in the config/locales/devise.en.yml and written for other languages), you just need to catch them.
One way is to add a layout/_messages partial:
<% flash.each do |name, msg| %>
<% if msg.is_a?(String) %>
<div class="alert alert-<%= name %>">
<a class="close" data-dismiss="alert">×</a>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
</div>
<% end %>
<% end %>
and render it in application.html.erb:
<%= render 'layouts/messages' %>
This has the benefit of catching all (devise and other) messages and playing nicely with bootstrap alert classes (if you use were using bootstrap).
.
Or if you are using slim:
- flash.each do |name, msg|
- if msg.is_a?(String)
div class="alert alert-#{name}"
a class="close" data-dismiss="alert"
| ×
= content_tag :div, msg, :id => "flash_#{name}"
= render 'layouts/messages'
.
Devise uses the rails standard :notice rather than :success but a you can add the success (green) styling to your css/scss (e.g. to bootstrap_and_overriders.css.scss):
.alert-alert {
#extend .alert-error
}
.alert-notice {
#extend .alert-success
}