Rails flash :notice doesn't work - ruby-on-rails

I have this code :
def create
login(params[:email], params[:password])
if current_user
flash[:notice] = "Welcome back #{current_user.email}"
return redirect_to_first_page
else
flash[:notice] = "Email or password is wrong. Try again !"
redirect_to root_url
end
end
when the login is successful the flash is set and the redirect to the first page is made.
This part is working. The second part is not setting the flash notice message. Then when the page is displayed no message from flash is show. What is different i've try to have
return redirect_to root_url
but nothing still not showing anything.
In my controller i have a helper like flash_notice all it does is return flash[:notice].
This is because the flash is always empty in a view but accessible in controller.
In the view i have just one line :
<%= flash_notice %>
I'm using rails 3.1

Chris Drappier is correct, the flash hash is current for one request only. You can invoke a "keep" method with
flash.keep[:notice]="This message will persist"
Personally, I like to keep the flash in question in params when needed. The gory details are here:
http://guides.rubyonrails.org/action_controller_overview.html#the-flash

Related

refactoring rails redirects with multiple ifs

In the app I am working on, the user can get to a new form from several different places. I need to redirect them back to where they came from. I solved it by passing a parameter in the link on the view, for example
= link_to "create a new post ยป", new_user_post_path(#current_user, :return_to => 'dashboard')
then in the new action in the controller like so
if params[:return_to] == 'dashboard'
session[:return_to]= 'dashboard'
end
now I am looking at the controller. what I need to do I can achieve by being really verbose, but I'm looking for a more elegant solution. Here is what I have now
if #user_post.save
flash[:notice] = "New Post Created"
if session[:return_to] == 'dashboard'
session.delete(:return_to)
redirect_to dashboard_path and return
else
redirect_to user_hub_path(#user)
end
else
flash[:error] = "Could not save post"
redirect_to new_user_post_path(#user)
end
This does what I need but I was hoping to tidy it up a little. I started looking at 1 line enumerators to see if I could do something like this...
if #user_post.save
flash[:notice] = "New post Created"
session[:return_to] == 'dashboard' ? redirect_to "#{session.delete(:return_to)}_path" : redirect_to user_hub_path(#user)
else
flash[:error] = "Could not save post"
redirect_to new_user_post_path(#user)
end
but it really doesn't like this part....redirect_to "#{session.delete(:return_to)}_path"
any advice? Guess I'm trying to get it to redirect and delete the session in one line and this is beyond my knowledge...
This looks like a good case for using Rails' built-in :back parameter, which, according to the Rails docs here, sends the user "Back to the page that issued the request. Useful for forms that are triggered from multiple places. Short-hand for redirect_to(request.env["HTTP_REFERER"])"
You can avoid passing a return_to param, and change your controller code to:
if #user_post.save
redirect_to :back, notice: "New Post Created" and return
else
redirect_to new_user_post_path(#user), flash: { error: "Could not save post" }
end
What about using send?
send takes a message name and optional arguments and forwards that to send's receiver (http://ruby-doc.org/core-2.2.0/Object.html#method-i-send)
path = send("#{session.delete(:return_to)}_path")
redirect_to path
In this case it sends the message to the current controller instance (same as just calling the ..._path method but gives the flexibility of the dynamic call)
Please instead of using a redirect_to variable of your controller, use the Referer Header.
HTTP referer (originally a misspelling of referrer) is an HTTP header field that identifies the address of the webpage (i.e. the URI or IRI) that linked to the resource being requested
In Rails is quite simple inside a controller
redirect_to request.referer
That is more elegant and efficient, because the session cookie storage can be expensive (cache storage) and could affect your HTTP cache proxies performance.

Unable to output flash msg from another method

I tried to use another function/method to redirect & output a notice, but it didn't work. It work fine within its own function.
def delete_sb
# #sb = SasaranBaru.find(params[:id])
# #sb.destroy
flash[:notice] = "fffff"
render_group("flash msg")
end
def render_group(notice)
logger.debug notice
flash[:notice] = notice
if params[:filter]
filter = prepare_filter_query(params[:filter])
redirect_to "/groups?#{filter.to_query}", notice: 'okokoko okokokok '
else
redirect_to "/groups", notice: 'hehehehe eheheheh'
end
end
there is no value for flash in my view.
Is there a redirect going on after this code? A flash is only valid for one request and then disappears.
One way to test this is use:
flash.keep[:notice]='ffffff'
and see if that shows up, but I suspect you are going through another controller in /group and redirecting again, losing the flash.

flash notice is lost on redirect, how to find out what's removing it?

There are many posts on SO about this ( respond_with redirect with notice flash message not working Why is :notice not showing after redirect in Rails 3, among others) , I've read at least 4 and still can't solve this issue.
I've got a portion of my site that lets people do some things before they create an account. I prefer this from a UX perspective. So they're allowed to do X and Y then they get redirected to the "Create account" page (uses Devise).
The redirect looks like:
if userIsNew
... stow information in a cookie to be retrieved later ...
redirect_to "/flash", flash[:notice]
=> "Ok, we'll get right on that after you sign up (we need your email)."
and return # this has to be here, since I'm terminating the action early
end
So "/flash" is a plain page that I made to test this. It doesn't do anything, has no markup of its own, just has the basic html from the application.html, which has this line in the body:
<% if flash[:notice] %>
<p><%= notice %></p>
<% else %>
No notice!
<% end %>
It says 'No notice' every time.
I have tried:
adding in a flash.keep to my before_filter in the static controller
using :notice => instead of flash[:notice] =>
putting the notice in a cookie and pulling that text out of the cookie and into a flash in the before_filter of my application controller
redirect_to :back with the flash[:notice] =>
It's either
flash[:notice] = 'blablabla'
redirect_to foo_url
or
redirect_to foo_url, notice: 'blablabla'
I'm overriding ApplicationController#redirect_to to call flash.keep so that any messages are persisted on redirect without having to explicitly call flash.keep in my controller actions. Works well so far. Haven't had a scenario yet where unwanted messages are persisted.
class ApplicationController < ActionController::Base
def redirect_to(*args)
flash.keep
super
end
end
Let me know if there are any scenarios where this isn't a good solution.
I have been fighting with the same problem for some time and none of the posts seemed to help.
It turns out that - like usually it happens - the the problem was in my code. I did have a "redirect_to" that I forgot about, which was clearing the flash.
Namely, "root_path" for me was served by the StaticPagesController's home method. "home" was doing some checks and then redirecting you to the user_path.
In my code I had in numerous places
redirect_to root_path, :flash => {error: #error}
These redirects were never displaying the flash because my hidden "home" controller serving the "root_path" was making another redirect that cleared the flash.
Therefore my problem was solved when i added the "flash.keep" in my "home" controller method
def home
if current_user
#user = current_user
flash.keep
redirect_to #user unless #user.no_role?
end
end
Faced the same problem, flash just disappeared after any redirect, nothing helped, then, I found that it was switched off...
Check your /config/application.rb for this:
config.middleware.delete ActionDispatch::Flash

How to return failed validation parameters to a rails model form that doesn't know what page it's on?

I have a small contact request form that appears on nearly every page in a site.
The form submits to the RequestsController create method. If all goes well, the request is saved in the Requests table and an e-mail is sent. If validation fails, I would like to redirect back to the referrer page.
Here is my create action...
def create
#request = Request.new(params[:request])
#location = Location.find(params[:location_id])
if #request.save
PodsMailer.contact_request(#request, #location).deliver
PodsMailer.contact_confirmation(#request, #location).deliver
flash[:notice] = "Thanks! Your message was sent. We will contact you shortly."
redirect_to :back
else
flash[:notice] = "Errors -- please check the form"
flash[:errors] = #request.errors
redirect_to ??????
end
end
My question is when validation fails, how do I redirect back to the referrer AND send the values entered into the form by the user? I can't use a named route because I don't know where the request is coming from.
"redirect_to :back" works fine by itself. But I can't figure out how to send parameters. The flash hash makes it through just fine. So there's got to be something simple I'm missing.
I have tried passing a params hash (:params => params[:request]) to every combination I can imagine of redirect_to with :back, url_for, request.referer... but with no luck.
I imagine there is some way to manually build the url and tack on query parameters, though I'm not exactly sure how to do that. But I was wondering if there is a Rails trick for passing parameters in this situation. Also, I'd like to implement a server-side solution before adding an AJAX solution.
Any help would be much appreciated. My first question here. Hopefully I've done this correctly.
Thanks--
Best here is to use AJAX and validation on client (that don't mean to deny server vilidation).
But for you I suggest this hacky solution:
def create
#request = Request.new(params[:request])
#location = Location.find(params[:location_id])
if #request.save
PodsMailer.contact_request(#request, #location).deliver
PodsMailer.contact_confirmation(#request, #location).deliver
flash[:notice] = "Thanks! Your message was sent. We will contact you shortly."
redirect_to :back
else
flash[:notice] = "Errors -- please check the form"
flash[:errors] = #request.errors
referer = request.referer.gsub(/\?.*/, "")
redirect_to referer + "?" + params[:request].map{|k,v| "request[#{k}]=#{v}"}.join("&")
end
end
But now you should in your request form do something like this:
<%= form_for Request.new(params[:request]) do |f| %>
...
or remove it into controller

Rails flash message remains for two page loads

I'm using a flash notice in a Rails application, with the following code:
flash[:notice] = "Sorry, we weren't able to log you in with those details."
render :action => :new
The flash message renders as expected on the 'new' action, but then it also shows on the next page the user visits (whatever that might be). It should only show once, but something's making it stick around.
There are two ways to solve this problem:
flash.now
flash.discard
One is to use
flash.now[:notice]
when your flash must be discarded at the end of the current request and is not intended to be used after a redirect.
The second one is to call
flash.discard(:notice)
at the end of the request.
The standard flash message is intended to be kept for the "next" request. E.g. you generate a flash while handling a create or edit request, then redirect the user to the show screen. When the browser makes the next request to the show screen, the flash is displayed.
If you actually generate a flash on the show screen itself, use flash.now.
Check the Ruby on Rails API documentation to see how the Flash hash works
Ok, I solved this. The way to get around it is to use:
flash.now[:notice] = "Sorry, we weren't able to log you in with those details."
render :action => :new
The key part being flash.now[:notice] instead of flash[:notice].
Or you can just call the action like this
flash.now[:notice] = "Sorry, we weren't able to log you in with those details."
render 'new' #or render :new

Resources