Flash messages in Rails getting carried over to the next page - ruby-on-rails

I am displaying error and notice messages in my application with a helper method as shown below.
def display_flash_content
[:error, :notice].map do |key|
collection = flash[key].blank? ? [] : (flash[key].respond_to?(:map) ? flash[key] : [flash[key]])
collection.map {|item| content_tag(:div, item, :class => key.to_s) }
end
end
and my layout has this
<%= display_flash_content %>
I need to display these messages when I do some operation and then redirect to a specific page (this is working fine). But my problem is this flash message persists between pages. It's coming twice between pages where it needs to be cleared immediately once it's displayed to the user.
How to handle this scenario. Please help me!

The way you are displaying the flash messages is fine. I think the problem is how you are setting them. If you are setting flash messages and not redirecting you can assign to flash.now[:notice] instead of flash[:notice], for example, and your message will not hang around after the redirect.

Related

Rails redirect flash[:notice] persisting when not supposed to

I have a button with a redirect_to that runs my controller action, which creates a new row for my model. The first time, it creates it correctly and redirects. After my redirect, I go to the previous page through the menu and repeat the same action. After I click on the button, it redirects to the correct page (which it shouldn't yet... caching?), and then my previous flash message displays. So it's duplicated. I put a debugger statement in to see where it happens on the second run through - it actually happens before my button action executes. After running the rest of the code, it redirects (but since it redirected prematurely, redirects to same page) correctly with the corresponding (second) flash. How do I get rid of the extra initial flash message?
Here's a picture showing what I mean:
If you look at the blue loading bar right underneath the URL, it shows that the page hasn't loaded yet (I stopped it with debugger statement as shown below). However, the redirect and flash has already happened, which it isn't supposed to, since the intended redirect and flash will happen after turbolinks finishes the page load.
Initial link:
<%= link_to create_wager_from_favorite_wager_path(favorite_wager), data: { confirm: 'Create this wager?' } do %>
Create Wager
<% end %>
Controller action:
def create_wager_from
debugger
# on second run through, the redirect and flash happens before I reach this point
#favorite_wager = FavoriteWager.find(params[:id])
#anchor = params[:anchor]
set_member_statuses()
result_message = #favorite_wager.create_wager_from_favorite(current_user)
respond_to do |format|
format.html { redirect_to my_wagers_path(:game => #favorite_wager.game), notice: "Wager created successfully!" }
end
end
At this point, it follows the standard path and I'm 99% sure the rest of the code is irrelevant.
I've tried checking the flash params at the point that the page with the button action loads, but it's empty. So I'm not sure what's causing this issue. Any insight appreciated.
Update: changing to flash.now[:notice] makes the duplicates stop, but the flash only displays on the first click of the button. Then it doesn't appear anytime after. And refreshing the page will allow the error to be repeated.
To prevent elements from being visible in cached pages (including previews), remove the element on turbolinks:before-cache. For example you could include something like this in your main application JavaScript file:
addEventListener('turbolinks:before-cache', () => {
document.querySelectorAll('.flash').forEach(element => element.remove())
})
For more on this checkout https://github.com/turbolinks/turbolinks#understanding-caching
After reading up on Turbolinks, I'd determined that the cause of this issue is the natural built-in functionality in turbolinks called a "page preview". This is where it will display the previous cached page as a sort of "preview" before the server response arrives, which gives the illusion that the page already loaded.
However, the cached redirect page in my case was cached the moment it was served up, meaning the flash message was also captured into that cache. So on the second time I clicked the create button, it would load the cached page with the flash, then redirect for real and flash again (like it's suppoed to).
So the solution here is to either a. disable all page previews or b. disable turbolinks for that specific link. I chose b. because it won't affect the rest of my program, at the expense that the blue loading motion is not longer there. Here is the solution below (very simple):
Before:
<%= link_to create_wager_from_favorite_wager_path(fw, :anchor => anchor), data: { confirm: 'Create this wager?' }, class: "red-btn create-favorite-wager-btn" do %>
Create Wager
<% end %>
After:
<%= link_to create_wager_from_favorite_wager_path(fw, :anchor => anchor), data: { confirm: 'Create this wager?' }, "data-turbolinks": "false", class: "red-btn create-favorite-wager-btn" do %>
Create Wager
<% end %>

In Ruby (2.2) on Rails How Do I Have A Confirmation Box Pop Up Then Redirect To Another Page

In my controller I have an if condition and I want an alert/confirmation box to pop up if it is satisfied, then when the user clicks "ok" to redirect to another page.
I've tried
flash[:alert] = 'Successfully checked in'
redirect_to check_in_path
However it just skips the alert part and goes straight to the redirect without an alert message.
My Ruby version is ruby 2.2.6p396 and rails is 5.0.1
Any help would be appreciated
You need to create a js.erb file. You can then use your existing rails code along with a js alert box. Js.erb files let you combine rails and JavaScript code in the same file. As mentioned flash[:alert] is not an alert box, alert is a css class.
Rails is limited to the respond to HTTP request with HTML. And what you describe sounds more like a JavaScript alert. What you tried, if configured properly*, will simply show the flash alert when the check_in_path page is rendered.
* Get familiar with how the flash works, Rails Guides
You have your controller set up correctly. The only other part I meant by configured correctly is that in your views you should display said flash message:
<% flash.each do |name, msg| -%>
<%= content_tag :div, msg, class: name %>
<% end -%>
It's common to use the name of the flash to style it to make to make it's intent clear; commonly red for failure, green for success.
you can do it as follows
render :update do |page|
page << "alert('Successfully checked in')"
page.redirect_to check_in_path
end
but partial rendering in controller is most commonly used together with Ajax calls. so you may have to make an ajax call to your action from your view page. Hope this will help you

Ruby on rails flash notice error

I have a problem with flash[:notice] = "Message" in Ruby on Rails.
I am trying to create login fault error message. My login fault handling is:
flash[:notice] = "Invalid username/password combination."
redirect_to(:action => 'login')
For the reason I don't know, alert just doesn't show up. I have red tons of possible solutions, but all of them just doesn't work for me. I am using Safari / Google Chrome web browsers.
Your controller code looks fine. I suspect your problem is not that you are calling the flash method incorrectly in your controller, but rather that you did not write the code (correctly) to display the flash in your view.
flash simply holds a message for your views to display. You are setting the message correctly, but you may not be displaying it properly. I can't tell because you aren't posting your view code.
For example, if this action is the result of submitting a user/login.html.erb form, based on your controller code, you would want to have the following code inside that view file:
<% flash.each do |key, value| %>
<div class="alert"><%= value %></div>
<% end %>
This code is a more basic version of what is described in this article.

What approach do you take for embedding links in flash messages?

The ability to have flash messages (notice, error, warning, etc) with embedded links is nice from a user interaction standpoint. However, embedding an anchor tag inside a flash message from the controller is dirty.
Let's assume that a flash message like this is good for usability*:
Example Flash Message Notice with an Embedded Link http://img.skitch.com/20090826-xbsa4tb3sjq4fig9nmatakthx3.png
(borrowed from DailyMile.com)
What tactic would you take between the controller and view to employ something like this cleanly?
Just thought I would share this, since found answer I was looking for elsewhere:
Works on rails 3.1
flash[:notice] = "Proceed to #{view_context.link_to('login page', login_path)}".html_safe
Glenn Gillen has an approach that he calls Useful Flash Messages in Rails.
I modified his code snippets to be a little more idiomatic (for me at least).
The controller fills the flash like this:
flash[:notice] = "Your profile was updated. %s"
flash[:notice_item] = ["Edit again?", edit_profile_path(#profile)]
You then might have helpers that look something like this:
def render_flash_messages(*keys)
messages = keys.collect do |key|
content_tag(:p, flash_message_with_item(key), :class => "flash #{key}") if flash[key]
end.join
content_tag(:div, messages, :id => "flash_messages") unless messages.blank?
end
def flash_message_with_item(key)
item = flash["#{key}_item".to_sym]
substitution = item.is_a?(Array) ? link_to(*item) : item
flash[key] % substitution
end
The view looks simply like this:
<%= render_flash_messages(:error, :notice, :warning) %>
The view (via the flash_message_with_item helper) is responsible for creating the anchor tag, but the controller manages what goes into the flash message including an optional resource for further action.
You could create a helper method to render out partials based on the value passed back in the flash message.

Ruby on Rails: Observers and flash[:notice] messages?

I'm trying send flash messages and welcome notices to users if it's their first time commenting; basically, something like this:
class CommentObserver < ActiveRecord::Observer
def after_save(comment)
if comment.user.new?
Mailer.deliver_welcome_package(comment)
flash[:notice] = "Welcome! We just delivered a welcome package to your email"
end
end
end
I'm not sure how I should display that flash message for users after they create their first comment. Should I put that flash message in the controller (with an additional "if comment.user.new?") or is there a way to display the flash message more efficiently?
Putting the flash message in the method seems fine to me.
I usually have a helper method in my application_helper file that checks flash and diplays.
def show_flash
[:notice, :error, :warning].collect do |key|
content_tag(:div, flash[key], :id => key, :class => "flash flash_#{key}") unless flash[key].blank?
end.join
end
I have three types of messages, notice, warning, and error, this checks to see if any of them are set, if so it prints them out, if not then nothing is printed.
In my layout i then have..
<% show_flash %>
Firstly, why are you observing comments? If you want to react to a new user, why don't you observe users?
To answer your question, I would definitely put the flash assignment in your controller, the reason being that the flash is a view level concern.
I used to use observers for sending mails, but have more recently just sent them in the controller. In this case, doing that would make your life a little simpler.

Resources