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 %>
<div id="nav-search" class="row collapse">
<div id="nav-search-field" class="small-21 columns">
<%= text_field_tag :search, nil, autocomplete: 'off' %>
</div>
<div id="nav-search-icon" class="small-3 columns">
<%= submit_tag ''.html_safe, class: 'button fa fa-search spin', name: 'submit' %>
</div>
</div>
<% end %>And here's the controller action:
def search
session[:return_to] ||= request.referer
if params[:search].to_i.zero?
flash[:error] = %Q[<i class="fa fa-times fa-fw"></i> 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[<i class="fa fa-warning fa-fw"></i> Sorry, we couldn't find a student with ID #{id}.].html_safe
redirect_to session.delete(:return_to)
end
end
endLastly, here's the code for rendering flash messages in application.html.erb:
<% flash.each do |key, value| %>
<div data-alert class="alert-box cbc-<%= key %>">
<%= value %>
<a href="#" class="close">×</a>
</div>
<% 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:
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!
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!
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.
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<script>alert('bad news!')</script>. 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?
%Q[<i class="fa fa-warning fa-fw"></i> Sorry, we couldn't find a student with ID #{id}.].html_safedef search session[:return_to] ||= request.
referer if !params[:search].numeric?
flash[:error] = %Q[<i class="fa fa-times fa-fw"></i> 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 . . .