In my lib/mercury/authentication.rb file I have
module Mercury
module Authentication
def can_edit?
if user_signed_in? and current_user.role == 'admin'
true
else
#flash[:notice] = "You are not authorized to view that page."
redirect_to root_path, notice:"You are not authorized to view that page."
end
end
end
end
And app/views/layouts/application.html.erb
<% if notice %>
<p class="alert alert-success"><%= notice %></p>
<% end %>
<% if alert %>
<p class="alert alert-danger"><%= alert %></p>
<% end %>
Yet the 'notice' never appears, even though it is working with Devise!
Thanks for any input!
Related
I am trying to show something if a user has 'messages'
views/messages/index.html.erb
<% if #user.messages.any? %>
You have messages!
<% else %>
Sorry, you have no messages
<% end %>
controllers/messages_controller.rb
class MessagesController < ApplicationController
def index
#user = current_user
#messages = #user.messages
end
When I have this code implemented even though the user has no messages (as confirmed by rails console :
user = User.find(1)
user.messages.any?
=> false
The message 'You have messages!' still appears
Also thought to add that the authentication is using the devise gem
<% if #user.messages.any? %>
<%= "User with id #{#user.id} has messages" %>
<% else %>
<%= "User with id #{#user.id} doesnt have messages" %>
<% end %>
This will show something like
User with id 5 has messages
or
User with id 6 doesnt have messages
Now verify this from rails console
User.find(5).messages.any?
try
<% if #user.present? %>
<%= puts "User is selected" %>
<% if #user.messages.present? %>
<%= puts "User have message" %>
<% end %>
<% end %>
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>
Got a small question in here.
My flash notice/alerts is inside [" "]
In my controller, I have to show the errors if the form isn't saved.
format.html { redirect_to new_project_procurement_management_plan_path, alert:"#{#project_procurement_management_plan.errors.full_messages}"}
Here's how i put flash into views:
_alert.html.erb:
<% [:notice, :error, :alert].each do |level| %>
<% unless flash[level].blank? %>
<div class="alert alert-<%= flash_class(level) %>" id="flash">
<a class="close" data-dismiss="alert" href="#">×</a>
<%= content_tag :p, flash[level] %>
</div>
<% end %>
<% end %>
And in my helper file:
#Flash Message
def flash_class(level)
case level
when :notice then "success"
when :error then "error"
when :alert then "error"
end
end
Now how can I remove my error display inside [" "]
Anyone knows where to configure it? Thanks.
EDIT
This is the validation message in my model:
def equality
self.items.each do |item|
errors.add(:base, "#{item.description.capitalize}: Quantity must be equal to the breakdown of quantity!") if item.months != item.qty
end
end
errors.full_messages returns an array of all the error messages which is why you see the brackets and quotes. You can use .to_sentence to turn that array into a readable sentence.
#project_procurement_management_plan.errors.full_messages.to_sentence
When users sign up to my application I have a welcome message appear on the home page using Devise's sign_in_count column.
def home
if current_user.sign_in_count == 1
flash.now[:notice] = "Welcome!"
end
end
The only problem though is it stays there until they sign out and sign back in. How can I make it show only once and disappear when the page is refreshed or changed? Is there some rails way to do this?
Thank you.
EDIT
application.html.erb
<body>
<div class="container">
<%= render "shared/flash_message" %>
<%= yield %>
</div>
</body>
_flash_message.html.erb
<% [:notice, :error, :alert].each do |level| %>
<% unless flash[level].blank? %>
<div class="span12">
<div class="<%= flash_class(level) %> fade in">
×
<%= content_tag :p, flash[level] %>
</div>
</div>
<% end %>
<% end %>
In your layouts/application.html.erb you should have something like this:
<% flash.each do |key, value| %>
<%= content_tag(:div, value, class: "flash #{key}") %>
<% end %>
Doing this way, should works as you expect.
EDIT
What if you verify for the current_user is already set?
def home
if current_user && current_user.sign_in_count == 1
flash.now[:notice] = "Welcome!"
end
end
EDIT 2
OK! Got it! The sign_in_count column from Devise will remain the same until the next login, so, it will always keep showing you the Welcome! message. To make this work as you expect you have to create a flag on it.
def home
if current_user && current_user.sign_in_count == 1
unless session[:display_welcome]
flash.now[:notice] = "Welcome!"
session[:display_welcome] = true
end
end
end
You can try using session or cookies.
If the user logs in for the first time, change the logic to compare against 0. After setting flash message update the sign_in_count to 1,
def home
if current_user.sign_in_count == 0
flash.now[:notice] = "Welcome!"
current_user.update_attribute(:sign_in_count, 1)
end
end
When I send wrong email, validation can't pass but error messages in views don't be displayed :(
I have in models:
validate :recipient_not_have_invitation, :notice => "That user have already invitation"
def recipient_not_have_invitation
errors.add :notice, 'That user have already invitation' if InvitationToGroup.find_by_recipient_email_and_group_id(recipient_email, group_id)
end
in controller:
(...)
if #invitation_to_group.save
Mailer.invitation_to_group(#invitation_to_group).deliver
redirect_to root_url, :notice => "Successfully send invitation to user #{#invitation_to_group.recipient_email}"
else
redirect_to new_invitation_to_group_path(:group_id => #invitation_to_group.group_id)
end
In views (invitation_to_groups/new.html.erb)
<h2>New Invitation to group </h2>
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<%= form_for #invitation_to_group do |f| %>
<% if #invitation_to_group.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#invitation_to_group.errors.count, "error") %> prohibited this user from being invitation:</h2>
<ul>
<% #invitation_to_group.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
(...)
The problem is that you are using redirect_to after else in your controller. So you are going to new action and in this action you have InvitationToGroup.new. So you build new object without errors ;) You need to use render method instesd.
PS. you should really consider using "formtastic". It will imporve your code in views. Please watch this two railscasts: http://railscasts.com/episodes/184-formtastic-part-1 and http://railscasts.com/episodes/185-formtastic-part-2