Rails flash notice won't go away in Safari?

I have a Rails 3.2 app that manages students. It has a fairly typical
nav
bar across the top (Foundation 5) which contains a quick search field.
The
nav bar is displayed on every page of the site.

If you enter a valid (numeric) student ID into the search field, you
simply
jump to that student’s page. If you enter text or other non-numeric
input,
you get a flash error asking for valid input. If you enter an id that’s
not
found, you get a flash notice saying it wasn’t found. In either of the
latter two cases, the controller should just drop you back to whatever
page
you came from and display the appropriate flash message.

For starters, here’s the search field in the view:

<%= form_tag search_students_path, method: ‘get’ do %>

<%= text_field_tag :search, nil, autocomplete: 'off' %>
<%= submit_tag ''.html_safe, class: 'button fa fa-search spin', name: 'submit' %>
<% end %>

And here’s the controller action:

def search
session[:return_to] ||= request.referer
if params[:search].to_i.zero?
flash[:error] = %Q[ Please enter a
numeric student ID.].html_safe
redirect_to session.delete(:return_to)
else
id = params[:search].to_i.abs
@student = Student.search(id).first
if @student
redirect_to @student
else
flash[:caution] = %Q[ Sorry, we
couldn’t find a student with ID #{id}.].html_safe
redirect_to session.delete(:return_to)
end
end
end

Lastly, here’s the code for rendering flash messages in
application.html.erb:

<% flash.each do |key, value| %>

<%= value %> ×
<% end %>

In Chrome and FireFox this works exactly as expected. The flash appears
for
one request, then disappears. However, in Safari, once the flash comes
up
it never goes away for that page. So if you get the error flash on the
home
page, for example, you can refresh all you want. It stays put. You can
go
to another page, and then come back, and it’s still there. The same is
true
for other pages. Once the flash message has appeared on a given page, it
doesn’t go away.

Thus my question: how can I get Safari to clear the flash after the
first
request?

I’m aware of the whole “flash vs. flash.now” issue when rendering pages.
But even then, the flash will disappear if you simply refresh. I
actually
tried flash.now in this case, but then the flash isn’t displayed at all
in
any browser.

Since this appears to be a browser-specific problem, here are some
further
stats on my system:

  • Mac OS X 10.9
  • Safari 7.0
  • Rails 3.2.16

One final observation. After playing around with this issue in Safari, I
noticed that if I clicked my bookmark for http://localhost:3000/, that
would clear the flash. Of course, all the navigation links in my site
layout contain relative paths, whereas the bookmark is calling a full
url.

Anyway, hope that made sense. Thanks in advance for your help!

On Wednesday, December 11, 2013 10:37:34 AM UTC, joshukraine wrote:

Since this appears to be a browser-specific problem, here are some further

Anyway, hope that made sense. Thanks in advance for your help!

Could this be a caching problem? Does the network inspector show fresh
requests being made to your app?

Unrelated, but I think you have an XSS bug - if i link to your search
page
with the search parameter set to 99999999 then I’m
pretty sure that js will get executed (the 99999 is to that to_i returns
non zero)

Fred

Hey Fred,

thanks for the reply. I’ve thought about the caching issue, though I’m
not
sure how to tell if this is in fact the problem. I’m not specifically
caching anything in my app, and I’ve cleared out the localhost data for
Safari. Also, all other flash notices in the app work fine, only this
one
sticks.

As I was discussing this issue with another developer, I decided to make
a
couple of short screen recordings (YouTube) that demonstrate what this
looks like in Safari as compared to Chrome and Firefox. If it helps, you
might have a look at these. Perhaps you’ll notice something that I’m
missing.

Here are some gists which provide more code context:

students_controller.rbhttps://gist.github.com/joshukraine/5510d064df6e4983f077

_top-nav.html.erbhttps://gist.github.com/joshukraine/544765c13157753dc166

application.html.erbhttps://gist.github.com/joshukraine/ed17d9101cba605f8cd9

Also, many thanks for the observation about the XSS bug. So far I have
not
been able to reproduce it though. For example, I entered this:
99999999. The search action did see
it
as numeric, but it stripped out the javascript and just returned a flash
saying that a student with ID 99999999 could not be found. I also tried
entering it via the URL, but that just crashed the redirect saying
“cannot
redirect to nil”. I guess I thought that Rails was sanitizing this
somewhere in the background, but maybe not. Any suggestions?

Thanks so much for the help!

On 11 December 2013 10:37, joshukraine [email protected] wrote:


In Chrome and FireFox this works exactly as expected. The flash appears for
one request, then disappears. However, in Safari, once the flash comes up it
never goes away for that page

I can’t see exactly how it might cause the problem you are seeing, but
often differences in appearance between browsers is due to html or
javascript errors on the page. In the browser view the page source
and copy/paste the complete page source into the w3c html validator
[1]. That will show you whether there are any errors. Fix them even
if you think that the error should not cause the problem you are
seeing. Use something like firebug to check for javascript errors.

Another thing to do is to compare the logs when running the two
browsers to see if there is any difference.

Colin

[1] The W3C Markup Validation Service

Hi Colin,

Thanks for the info. Did as you suggested and tested the HTML. There
were
six errors, all of which were due to the way Foundation uses li tags in
the
nav bar dropdown menu. As this section is unrelated to the search
feature,
I removed these tags and revalidated. There was also a warning about the
icon I’m using in the search submit button, so I replaced that with the
text ‘GO’. With those changes, the document validated. (I was also
careful
to validate the HTML which includes the flash message.) Unfortunately,
these changes did not alter the flash behavior.

Also, I check the dev console in Chrome, and the only problem I could
with
JavaScript was a warning about a deprecated method in jQuery:
event.returnValue is deprecated. Please use the standard
event.preventDefault() instead.

Thanks anyway!

On Thursday, December 12, 2013 7:09:21 PM UTC, joshukraine wrote:

Hey Fred,

thanks for the reply. I’ve thought about the caching issue, though I’m not
sure how to tell if this is in fact the problem. I’m not specifically
caching anything in my app, and I’ve cleared out the localhost data for
Safari. Also, all other flash notices in the app work fine, only this one
sticks.

Have you looked at whether the search parameters are being included in the
links? Although if you’re not going to the search action I would assume
that they wouldn’t be used even if they were.

Have you tried inspecting the individual http requests coming back? The
Set-Cookie response header should be showing you changes to the session
your rails app is making, and obviously the Cookie header on requests
contains the current session data (The cookie value has two parts,
separated by --. The second part is the signature, and the first part is
base64 encoded marshal data so somehting like
Marshal.load(Base64.decode64(’…’)) should turn the data back into a
ruby
object). Does the cookie on the next request contain the set-cookie
value
from the previous request? (I have in the past seen race conditions
with
sessions, although only with overlapping http requests)

As I was discussing this issue with another developer, I decided to make a
couple of short screen recordings (YouTube) that demonstrate what this
looks like in Safari as compared to Chrome and Firefox. If it helps, you
might have a look at these. Perhaps you’ll notice something that I’m
missing.

Also, many thanks for the observation about the XSS bug. So far I have not
been able to reproduce it though. For example, I entered this:
99999999. The search action did see it
as numeric, but it stripped out the javascript and just returned a flash
saying that a student with ID 99999999 could not be found. I also tried
entering it via the URL, but that just crashed the redirect saying “cannot
redirect to nil”. I guess I thought that Rails was sanitizing this
somewhere in the background, but maybe not. Any suggestions?

My apologies, your code is fine. It’s worth you understanding how the
rails
sanitization works though

When you do

%Q[ Sorry, we couldn’t find a student
with ID #{id}.].html_safe

you are telling rails that everything in that string is safe. So if id
contained something untrusted, you’d be in trouble. However, since you
called .to_i on that earlier on you’re fine (I’d skipped over that line)

Fred

Hi all,

Just a heads-up to let you know that I’ve created a test app and pushed
it
to GitHub. I have successfully reproduced this bug with the test app.
Steps
to reproduce are in README.md in the repo.

Thanks again for your assistance!

Joshua

Hey Fred,

Thanks for the response. The search parameters are of course included in
the initial GET request, but as best I can tell from the log output they
are not included when the user is sent back to the referring page. As to
your question about the cookies, I’m not sure. I’ve been using
logger.debug
to inspect the session, but I may be missing something. Here’s what I’ve
got in my search action right now:

def search
session[:return_to] ||= request.referer
if !params[:search].numeric?
flash[:error] = %Q[ Please enter a
numeric student ID.].html_safe

logger.debug("@@@@ flash: #{flash}")
logger.debug("@@@@ session: #{session}")
logger.debug("@@@@ request.referer: #{request.referer}")

redirect_to session.delete(:return_to)

else…

The following two gists contain the log output I’m seeing from Chrome
and
Safari. Comments are mine.

I’d love to understand more about inspecting cookies, requests, and so
forth. If there’s more I can do I’m happy to try. Thanks for your help!

Josh

On Sunday, December 15, 2013 1:24:23 PM UTC+2, Frederick C. wrote:

Safari. Also, all other flash notices in the app work fine, only this one
separated by --. The second part is the signature, and the first part is
looks like in Safari as compared to Chrome and Firefox. If it helps, you
entering it via the URL, but that just crashed the redirect saying "cannot

you are telling rails that everything in that string is safe. So if id
contained something untrusted, you’d be in trouble. However, since you
called .to_i on that earlier on you’re fine (I’d skipped over that line)

Fred

On Sunday, December 15, 2013 1:24:23 PM UTC+2, Frederick C. wrote:

Safari. Also, all other flash notices in the app work fine, only this one
separated by --. The second part is the signature, and the first part is
looks like in Safari as compared to Chrome and Firefox. If it helps, you
entering it via the URL, but that just crashed the redirect saying "cannot

you are telling rails that everything in that string is safe. So if id
contained something untrusted, you’d be in trouble. However, since you
called .to_i on that earlier on you’re fine (I’d skipped over that line)

Fred

On Sunday, December 15, 2013 1:24:23 PM UTC+2, Frederick C. wrote:

Safari. Also, all other flash notices in the app work fine, only this one
separated by --. The second part is the signature, and the first part is
looks like in Safari as compared to Chrome and Firefox. If it helps, you
entering it via the URL, but that just crashed the redirect saying "cannot

you are telling rails that everything in that string is safe. So if id
contained something untrusted, you’d be in trouble. However, since you
called .to_i on that earlier on you’re fine (I’d skipped over that line)

Fred

On Sunday, December 15, 2013 1:24:23 PM UTC+2, Frederick C. wrote:

Safari. Also, all other flash notices in the app work fine, only this one
separated by --. The second part is the signature, and the first part is
looks like in Safari as compared to Chrome and Firefox. If it helps, you
entering it via the URL, but that just crashed the redirect saying "cannot

you are telling rails that everything in that string is safe. So if id
contained something untrusted, you’d be in trouble. However, since you
called .to_i on that earlier on you’re fine (I’d skipped over that line)

Fred