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
Related
I read the documentation on Rails Validation, but didn't see much about how to work with errors in the controller.
Question -- Are render :new and render :edit when .save fails the proper way to show the errors after submitting the form?
Also, is there a way that I can keep the polls/new and polls/edit routes the same as when the form was initially loaded?
In my view I have the #poll.errors.any? ... #poll.errors.full_messages.each do ... block. These errors are successfully called if I have the following code in my controller, with render :new being the main point of interest:
class PollsController < ApplicationController
def create
#poll = Poll.create(poll_params)
if #poll.save
redirect_to polls_path
else
render :new
end
end
The form shows up, but my route changes from polls/new back to polls and none of my options are built. I also tried redirect_to new_poll_path but of course that starts from scratch and shows no errors.
Take the following scenario: A user navigates to the form in your new action, enters some data, and presses "submit". By default (i.e. assuming you're using restful routes), rails will submit your form to the create action in your controller. Assume that the user entered some data that was incorrect and would cause #poll.save to fail. In your case, this code would run:
render :new
In this case, you have told rails to simply render the new partial again. However, since you've told rails to render the new partial from your create action, you will see /polls in your url bar since /resource_name is how rails implements the create portion of its restful routing system (and you've defined your resource to be called "polls".
To answer this question:
Are render :new and render :edit when .save fails the proper way to show the errors after submitting the form?
The short answer is yes. In rails, this is typically the preferred way of showing errors to users who enter incorrect data into a form. However, if you wanted to ensure that /edit or /new was in the url bar after an unsuccessful form submission, you would need to replace:
render :new
with
redirect_to new_poll_path, alert: #poll.errors.full_messages
This solution will cause the errors in your #poll object to be displayed in your flash messages area (assuming you have that set up). However, I don't personally like this solution much because flash messages typically aren't intended to be used this way. This begs the question:
Why can't I use #poll.errors.full_messages after a redirect?
The reason for this is because your #poll object (in the create action) is carrying the error messages. As soon as #poll.save fails, your #poll object will be carrying the error messages that caused the .save method to fail. If you were to redirect away from the create action back to the new or edit actions, the #poll object with the errors would be replaced by a new #poll object as defined in either the new or edit actions in your controller. Therefore, using render allows you to give the #poll object with the error messages back to the appropriate action so that the error messages can be displayed.
I have standard bug with notices, but I can't make it work correctly.
I'm calling some after_filter to verify if updated data is correct.
Here is code from before filter with notices:
after_filter :verify, :on => :update
def verify.
...
if account_status == "VERIFIED"
flash[:success] = "Your account is verified"
else
flash[:error] = "Sorry, your account is not verified or you entered wrong credentials"
end
so when I use this notices stays on my page after redirection to other page.
When I'm using flash.now[:notice] I lost my messages and they didn't show.
I know, that is standard problem, but I can't find solution that was working for me.
at this moment (before click) my account isn't verified(not correct data).So I'm change them into correct
After I click save it shows me this:
( http://i.imgur.com/j3uw8.png )
but after refreshing page:
( http://i.imgur.com/4EtrL.png )
If you want to set a flash notice that doesn't persist you need to do
flash.now[:notice] = "..."
not flash[:now]
If you want a flash value to be carried over to another request, use the keep method:
def index
# Will persist all flash values.
flash.keep
redirect_to users_url
end
I am implementing in Ruby on Rails, and when a user filled in something wrong, or something wrong is happened, the user has to go back to the previous page, and with a correct error message. I tried to do this with:
redirect_to 'javascript:history.go(-1)', flash.now[:error] =>"Something went wrong"
Now, this goes back to the previous page, but this without the flash error? Does someone know how to fix this?
Thanks in advance!
EDIT: I tried :
redirect_to 'match', :notice => 'Something went wrong'
Match is the previous page, but now I get an error from my browser:
No data received
Unable to load the webpage because the server sent no data.
You can't mix Javascript and Ruby this way. Your Javascript call does not make any side-server action, so your ruby code is never executed.
default error handling of Ruby on Rails is quite convenient and if you can, it's better to use it.
If you really cannot use it, you'll have to choose between Ruby and Javascript for this matter. The recommended way is the Ruby way :
redirect_to user_path(#user), :notice =>"The user was successfully created"
see this post of Ryan for more detail. I am not sure if this is possible in Javascript, because you'll have to pass error information to the previous page without reloading it.
Use:
redirect_to :back, :flash => {:error => "Error"}
flash.now triggers the flash in the same rendering sequence. After a redirect you are on a newly rendered page and therefor your shouldn't use flash.now but something like
redirect_to :back, error: 'Something went wrong'
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
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