My flash messages are appearing twice and my web research tells me this is due to render and redirect displaying the messages. I think I need to use flash.now[] or flash[] somewhere to sort this but I can't work out where it needs to go
guidelines_controller.rb
def update
#guideline = Guideline.find(params[:id])
respond_to do |format|
if #guideline.update_attributes(params[:guideline])
#guideline.update_attribute(:updated_by, current_user.id)
format.html { redirect_to #guideline, notice: 'Guideline was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "show" }
format.json { render json: #guideline.errors, status: :unprocessable_entity }
end
end
end
layouts/application.html.erb
<div class="container">
<% flash.each do |type, message| %>
<div class="alert <%= flash_class type %>">
<button class="close" data-dismiss="alert">x</button>
<%= message %>
</div>
<% end %>
</div>
application_helper.rb
def flash_class(type)
case type
when :alert
"alert-error"
when :notice
"alert-success"
else
""
end
end
guideline_controller.rb
def show
#guideline = Guideline.find(params[:id])
if #guideline.updated_by
#updated = User.find(#guideline.updated_by).profile_name
end
if User.find(#guideline.user_id)
#created = User.find(#guideline.user_id).profile_name
end
respond_to do |format|
format.html # show.html.erb
format.json { render json: #guideline }
end
end
You can do something like this in order to save some lines of code, and display the messages just once:
<%- if flash.any? %>
<%- flash.keys.each do |flash_key| %>
<%- next if flash_key.to_s == 'timedout' %>
<div class="alert-message <%= flash_key %>">
<a class="close" data-dismiss="alert" href="#"> x</a>
<%= flash.discard(flash_key) %>
</div>
<%- end %>
<%- end %>
By using flash.discard, you show the flash message an avoid rendering twice
Just putting this here for anyone else having trouble.
I had flash messages appearing twice because I had something in application.html.erb telling my app to display flash messages, but I had previously generated views with rails generate scaffold posts etc, so that had automatically added the flash messages to all the views.
So the solution was to remove them from the views.
Here's a great tutorial that demonstrates removal for just one model/view
So basically, if you have something like this in your application.html.erb:
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
Then simply remove the equivalent from each of the views. I.e. remove this line from the top of each view
<p id="notice"><%= notice %></p>
I was also having the same issue and also due to another call of <%= render 'shared/alerts' %> later after my check for flash. I liked #rorra's idea of doing a flash_key. But here in the year 2020, it wasn't working as #tessad stated. It would show the message, but not format in bootstrap correctly.
I was able to change their code to work with BootStrap 4. It even dismisses as it is supposed to. The three things that needed to change were all dealing with the class of the div used to display the flash notice.
<div class="alert-message <%= flash_key %>">
alert-message becomes just alert, and the flash_key has to have alert- before it.
<div class="alert alert-<%= flash_key %>">
The last thing is I was sending it to the view from the controller as flash[:notice], which is not a recognized bootstrap alert. When I changed it to flash[:warning] it showed up correctly.
Here is the final code that worked for me. Putting it here in case anyone needs it now 7 years after the initial answer was given.
<div id="container">
<%- if flash.any? %>
<%- flash.keys.each do |flash_key| %>
<%- next if flash_key.to_s == 'timedout' %>
<div class="alert alert-<%= flash_key %>">
<a class="close" data-dismiss="alert" href="#"> x</a>
<%= flash.discard(flash_key) %>
</div>
<%- end %>
<%- end %>
</div>
Related
When a user creates a ticket my site redirects to the ticket and displays a notice that informs the user it has been created. At the moment it is a standard notice with no styling.
This is the block that redirects - I need to add a class to the notice. How can this be achieved?
redirect_to #ticket, notice: 'Ticket was successfully created.'
Add a class to a tag, maybe a div, and then wrap your notice there, like:
<div class="notice">
<%= notice %>
</div>
But what's usually done, is to assign a class to the html tag dinamycally, this way if the flash message is notice or other, then you have the styles defined for each of them, like:
<% flash.each do |key, message| %>
<p class="<%= key %>">
<%= message %>
</p>
<% end %>
In rails 5 you can use 'add_flash_types' method. Just add it to ApplicationController and include the types you want:
class ApplicationController < ActionController::Base
add_flash_types :success, :warning, :danger, :info
on your controller use the appropriate type instead of 'notice':
redirect_to #ticket, success: 'Ticket was successfully created.'
and then you can automate your view:
<% flash.each do |message_type, message| %>
<div class="alert alert-<%= message_type %>">
<%= message %>
</div>
<% end %>
source:
http://api.rubyonrails.org/v5.1/classes/ActionController/Flash/ClassMethods.html#method-i-add_flash_types
I have something like
<div class="userInput">
<%= form_for :scribble do |f| %>
<%= f.text_area :scribble, cols: 65, rows: 4,:maxlength => 255%>
<%= f.submit %>
<% end %>
</div>
1)My Scribble model has min and max character length validation, now how do I print the error messages here. If it is an instance variable I know how to print, but this is a symbol.
2) This code is present in the application.html.erb. I am not able to understand how do I move it into a view of Scribble controller other than appliation. Problem is this form is not independent, it is a part of action index display of controller Scribbles,(and the form should be displayed always) and action index is already doing listing of scribbles.
Controller
def index
#scribbles = Scribble.order("scribbles.scribble DESC").all
end
def show
end
def new
end
def create
#scribble = Scribble.new(profile_params)
#scribble.likes =#scribble.dislikes =#scribble.shares=0;
#scribble.save
#scribbles = Scribble.order("scribbles.scribble DESC").all
render :index
end
Here how i out-put any errors or validation messages:
Controller:
def create
#scribble = Scribble.new(profile_params)
#scribble.likes =#scribble.dislikes =#scribble.shares=0;
if #scribble.save
flash[:notice] = "Scribble is successfully created"
redirect_to root_url
else #
render 'index'
end
end
Views:
Create a partial to show error messages if any e.g _error_messages.html.erb
<% if object.errors.any? %>
<div id="error_explanation">
<div class="alert callout text-center" data-closable>
<p><strong>This form contains <%= pluralize(object.errors.count, 'error') %>.</strong></p>
<ul>
<% object.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<button class="close-button" aria-label="Dismiss alert" type="button" data-close>
<span aria-hidden="true">×</span>
</button>
</div>
</div>
<% end %>
Render errors:
Now you can call <%= render 'layouts/error_messages', object: #scribble %> and put it anywhere in your views to render the errors validation. note: the object is passed, so it can be re-use to any form. credits to Hartl Tutorial.
I have a list of group and I want to edit a single group name via modal. I use edit.js.erb file and bootstrap modal.
There are two cases, both wrong.
First:
Using "remote: true" in Partial and link_to(in single row file)
Then modal is displaying, but after SAVE button clicked always is rendering again and never close. (I don't know why)
Second:
Delete remote:true from partial.
Then modal is displaying, I can even save the changes. But when I type wrong name (blank or too long), line "render 'edit'" from Controller crash. (error: "Missing template groups/edit, application/edit...". I think rails doesn't know about edit.js.erb then, but how to repair it?
Have you got any ideas about this situation ?
Controller
def edit
#group = current_user.groups.find_by(id: params[:id])
respond_to do |format|
format.js # actually means: if the client ask for js -> return file.js
end
end
def update
#group = current_user.groups.find_by(id: params[:id])
if #group.update_attributes(group_params)
flash[:success] = "Nazwa grupy została zmieniona"
redirect_to groups_path
else
render 'edit'
end
end
Partial for displaying form_for in modal
<%= form_for(#group, remote: true) do |f| %>
<div>
<%= render 'shared/error2_messages', object: f.object%>
<p>
<%= f.label :name, "Nazwa" %>
<%= f.text_field :name, class: 'form-control'%>
</p>
</div>
<%= f.submit yield(:button_name), class: "btn btn-primary" %>
<% end %>
edit.js.erb file
<% provide(:button_name, 'Zapisz zmiany') %>
$('.modal-title').html("Edytuj nazwę grupy");
$('.modal-body').html("<%= escape_javascript( render partial: 'layouts/group_data_form', locals: {group: #group} ) %>");
$('#myModal').modal();
Single row in a list
<li id="group-<%= group.id %>" class="list-group-item">
<span class="group-name"><%= group.name %></span>
<%= link_to edit_group_path(group.id), remote: true, :class => "edit-option btn" do %>
<i class="fa fa-pencil-square-o fa-2x" ></i>
<% end %>
<%= link_to group, method: :delete, data: { confirm: "Na pewno chcesz usunąć tę grupę?" }, :class => "delete-option btn btn-danger" do %>
<i class="fa fa-trash-o" > usuń</i>
<% end %>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Zmień nazwę grupy</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Anuluj</button>
</div>
</div>
</div>
</div>
This looks like a follow-up to your question of yesterday.
I won't say both your approaches are wrong, I'll say you are conbining two right approaches in such a way...
(1) since you used js to send save (with the use of remote: true on your form), all you need to do is to close the modal on successful save as will be defined from update.js.erb (just like you defined an edit.js.erb for the format.js in edit) as follow:
#update.js.erb
<% if #group.errors.empty? %>
$('.modal-body').html("");
$('#myModal').modal('hide');
$("#notice").html("Group was successfully updated.");
<% else %>
$("#notice").html("Error! Group not updated.");
<% end %>
#controller update action
def update
#group = current_user.groups.find_by(id: params[:id])
#group.update_attributes(group_params)
respond_to do |format|
format.html
format.js
end
end
What you essentially did here is to check if there is no error in the #group object(this will be true if #group got saved), then emptied your Modal and then hid it from view.
(2) When you removed remote: true you are no longer using js, so when you have a wrong name, the update does not work, and the render :edit portion of your update method kicks in. However, your edit action only specifies format.js, So what you may have to do in this case is to add format.html if you want to call with html.
def edit
#group = current_user.groups.find_by(id: params[:id])
respond_to do |format|
format.js # actually means: if the client ask for js -> return file.js
format.html
end
end
Note however that this may not open your modal, it will go to the edit_group_path of your app, which is the /groups/:id/edit
I've been trying to search for an answer on here but I can't find anything that works. I have implemented a :success and :danger flash notice to my rails app. It WAS working completely fine, i.e :success was green and :danger was red, with a close button and all, BUT since adding some mailer files my :success is now showing up red??
application.html.erb excerpt:
<body>
<div class="container">
<% flash.each do |key, value| %>
<%= content_tag :div, class: "alert alert-#{key == 'notice ? 'success' : 'danger'}" do %>
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<%= value %>
<% end %>
<% end %>
<%= yield %>
</div>
</body>
contact_mailer.rb
class ContactMailer < ActionMailer::Base
default to: 'justindavidson23#gmail.com'
def contact_email(name, phone, email, event_type, body)
#name = name
#phone = phone
#email = email
#event = event_type
#body = body
mail(from: email, subject: 'Contact Form Message').deliver
end
end
contacts_controller.rb
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(contact_params)
if #contact.save
name = params[:contact][:name]
phone = params[:contact][:phone]
email = params[:contact][:email]
event = params[:contact][:event_type]
body = params[:contact][:comments]
ContactMailer.contact_email(name, phone, email, event, body).deliver
flash[:success] = 'Message Sent.'
redirect_to new_contact_path
else
flash[:danger] = 'Error occurred, messgage not sent.'
redirect_to new_contact_path
end
end
end
private
def contact_params
params.require(:contact).permit(:name, :phone, :email, :event_type, :comments)
end
and, contact_email.html.erb
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<p>New Message from Hoot and Holla's Contact form, from <%= "#{#name}, #{#email}" %></p>
<p><%= #phone %></p>
<p><%= #event %></p>
<p><%= #body %></p>
</body>
</html>
I repeat that this was all working completely fine before the mailer stuff went in...but now i'm just baffled. Please help!
Sometimes you are going to want to use more than notice and success, like the Bootstrap alerts info, danger, and warning.
Here is the solution I would recommend:
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %> alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">×</span></button>
<%= value %>
</div>
<% end %>
That way, when you call flash[:success] = 'foo', your key would be success, and likewise for info, warning, danger, etc. This way you can utilize all of the different Bootstrap alerts.
With this method, you will have to add 2 more CSS classes, that extend the Bootstrap classes, if you want to use the syntax notice: 'hello world', or alert: 'oops' in your redirections, like redirect_to root_url, notice: 'welcome home'.
If you do want to use these, then you can use Sass, like below.
.alert-alert {
#extend .alert-danger;
}
.alert-notice {
#extend .alert-warning;
}
Since my comment earlier on the mailer callback was more of a side note and unrelated to this question, I made a simple gist for ya.
In your flash loop, you are only checking flash[:notice] there. if there is flash[:notice], you applying alert-success. unless it applying alert-danger. So, what i change here. i am applying alert-success for both flash[:success] & flash[:notice]. So,
Do in _flash.html.erb -
<%= content_tag :div, class: "alert alert-#{['success','notice'].include?(key) ? 'success' : 'danger'}" do %>
Try this code in application layout...
<div id="wrapper">
<div id="page-wrapper">
<div class="row">
<div class="col-lg-12">
<% flash.each do |name, msg| %>
<%= content_tag(:div, msg, :id=>"#{name}", :class `enter code here`=>"alert alert- info") %>
<%end%>
</div>
</div>
</div>
</div>
<script type="text/javascript">
window.setTimeout(function()
{
$("#notice").fadeTo(500, 0).slideUp(500, function()
{
$(this).remove();
});
}, 5000);
</script>
<%= yield%>
Oh thanks so much #AmitSuroliya!! This has worked perfectly!! I'm trying to work out what is actually happening here in the code...i don't suppose you could give a short explanation as to why this works could you??...if not thankyou anyway!! I appreciate it so much :)
Justin
PS for people having the same problem and reading this....that solution was copying and pasting this into my application.html.erb file and replacing the content_tag line i had...NOT creating a partial called _flash.html.erb ..just incase anyone was getting confused there :)
I am trying to use Bootstrap styles to Display the Flash messages with color to the users.
Controller
def create
#category = Category.new(category_params)
# Assigning default values
#category.status = 1.to_i
if #category.save
redirect_to admin_categories_path, :flash => { :success => "Category was successfully created." }
else
flash[:error] = "Category could not be save. Please try again."
render :new
end
end
View
<%= render 'admin/partials/flash_message' %>
Partial
<% if flash.present? %>
<%= flash.inspect %>
<% flash.each do |key, value| %>
<div class="<%= flash_class(key) %> fade in widget-inner">
<button type="button" class="close" data-dismiss="alert">×</button>
<%= value %>
</div>
<% end %>
<% end %>
Helper
# Flash Messages
def flash_class(level)
case level
when :notice then "alert alert-info"
when :success then "alert alert-success"
when :error then "alert alert-error"
when :alert then "alert alert-error"
end
end
Output
I am not able to pass the key to the helper function. I am assuming it sends blank.
This is the HTML that gets outputted
<div class=" fade in widget-inner">
<button data-dismiss="alert" class="close" type="button">×</button>
Category could not be save. Please try again.
</div>
I am not able to figure out why foreach is not able to extract the key and value pair.
on inspect i get the following
#<ActionDispatch::Flash::FlashHash:0x007fc0e74dfa58 #discard=#<Set: {}>, #flashes={"error"=>"Category could not be save. Please try again."}, #now=nil>
in Rails 4, it supports only strings. So i had to change the Helper to the following
# Flash Messages
def flash_class(level)
case level
when 'notice' then "alert alert-info"
when 'success' then "alert alert-success"
when 'error' then "alert alert-danger"
when 'alert' then "alert alert-warning"
end
end
**Edit: According to Deep Suggestions **
By Changing the Flash Partial to
<% if flash.present? %>
<% flash.each do |key, value| %>
<div class="alert alert-<%= key %> fade in widget-inner">
<button type="button" class="close" data-dismiss="alert">×</button>
<%= value %>
</div>
<% end %>
<% end %>
And by Just Extendting the BootStrap Classes as follows we can eliminate the Helper class all together.
alert-notice { #extend .alert-info; }
alert-error { #extend .alert-danger; }