I'm having difficulty getting my notices to display in my Rails 5 view. I have this before_filter method set up in a controller:
def check_email_confirmed!
redirect_to controller: "users", action: "edit", notice: 'Please confirm your email.' unless current_user.email_confirmed
end
and in my view I have this
<% if flash[:notice] %>
<p class="flash-notice"><%= flash[:notice] %></p>
<% end %>
but despite the fact that I know the notice is getting set (I see it in my URL) the above is not getting invoked in my view (I see no HTML with the class="flash-notice").
Is there some other way I should be setting flash notices in a redirect? Or should I be using a redirect at all (someone told me there might be some security risks in embedding messages in the URL query string)?
You're currently setting a parameter with the key notice, not setting the flash in your session.
To accomplish this the way you're doing it you would have to do:
<p class="flash-notice"><%= params[:notice] %></p>
Most Rails apps that I've worked on set the session[:flash] in the controller method, in which case you would do:
unless current_user.email_confirmed
redirect_to edit_user_path(current_user)
flash[:notice] = 'Please confirm your email.'
end
Unless you have a good reason to pass the notice text as a URL param, I'd recommend doing it this way.
Try
flash[:notice] = 'bla'
redirect_to controller: "users", action: "edit"
I'm pretty sure that
redirect_to edit_user_path(user), notice: 'bla'
Will also work. For some reason your syntax apparently doesn't pick up the notice modifier. But you'll have to assign user to your current user for that to work obviously.
Related
I have a simple Rails application where I create objects (such as posts). So far I can edit and delete them, one by one, but now I want to have a <%= notice %> echoing the name of the deleted object after confirming its deletion. Is this possible? If so, how?
This is an extremely common task in Rails, and the idiomatic solution is to forward some data about the deleted record to the subsequent GET request via the the flash array.
Your controller's destroy action should look something like this:
def destroy
#post = Post.find(params[:id])
#post.destroy
redirect_to posts_path, notice: "#{#post.name} was deleted"
end
In your index action, you'll be able to access flash[:notice] to get the string generated in the previous action.
You need to store the details you want to echo (e.g. the name) somewhere, because the object itself will be gone after a redirect. I would use the flash for that:
# in the controller
def destroy
thing = Thing.find(params[:id])
thing.destroy
redirect_to things_path, :notice => "Thing #{thing.name} was deleted"
end
# in the index view
<% if flash[:notice] %>
<div class="notice"><%= flash[:notice] %></div>
<% end %>
When I save a new user the notice fires twice. Any suggestions on how to get it to fire once? I am also using Sorcery
def create
#user = User.new(user_params)
if #user.save
redirect_to #user, notice: 'Profile successfully created.'
auto_login(#user)
else
render :new
end
end
As per the code snippet given above, I don't think notice will appear twice. There is nothing wrong in your code. There is one possible chance that in your application layout displaying notice is defined once and in your current view template it's defined again. That's why it's showing twice.
Flash:
The flash provides a way to pass temporary objects between actions. Anything you place in the flash will be exposed to the very next action and then cleared out.
A notice can't fire twice according to your code. In your app you somewhere have this code twice (my guess would be in your layout file and then your view)
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" %>
<% end %>
Here are the actions for my messages controller:
def new
#message = Message.new
end
def create
#message = Message.new(message_params)
if #message.valid?
Contactform.contact(#message.name, #message.town, #message.email, #message.content).deliver
redirect_to 'messages#new', flash: { success: "Sent Message" }
else
redirect_to 'messages#new', flash: { alert: "Message Error" }
end
end
This is what I want to happen:
I go to the 'new' route, a #message instance is created, and in the 'new' view there is a form where we can update this 'Message' instance' attributes.
Now, I'm following a tutorial, but it seems a little work-aroundy. When we 'submit' the form, we are automatically taken to the 'create' action, and a second message instance is created and populated with the old instances attributes.
If the attributes pass the Message model's validations, the attributes are passed into the 'Contactform' mailer's 'contact' action, which delivers the message. We are then redirected to the 'new' view, and the flash is populated with a "Sent Message" string, that we can see when we arrive at the 'new' view.
If the attributes fail the Message model's validations, we are then redirected to the 'new' view, and the flash is populated with a "Message Error" string, that we can see when we arrive at the 'new' view.
What actually happens
Everything works perfectly, apart from the flash. Once it's populated with either the 'success' or 'alert' message, it doesn't change until I browse to another page. Then it gets the updated message, on a new page, so I think because I'm coming back to the same location, the flash isn't updated for some reason.
How can I get the flash to behave normally, despite us coming back to the same page?
Update
Just to say again, it works perfectly if I get redirected to another page. Just because it's the same page, the flash doesn't get updated.
Also, I now have this in the view: Still doesn't do anything.
<% if !flash.empty? %>
<% flash.each do |index, value| %>
<div class = "alert alert-<%= index %>"> <%= value %></div>
<% end %>
<% flash[:error] = flash[:message] = flash[:notice] = nil %>
<% end %>
If you want the flash to show up within the same request (i.e. without a redirect taking place), you'll need to use flash.now. Here's the explanation in the rails docs:
By default, adding values to the flash will make them available to the next request, but sometimes you may want to access those values in the same request. For example, if the create action fails to save a resource and you render the new template directly, that's not going to result in a new request, but you may still want to display a message using the flash
See section 5.2.1 http://guides.rubyonrails.org/action_controller_overview.html
I am using Rails 3.1.0 and I would like to understand why the following code in a controller action doesn't properly display the flash[:warning] message even if I state a <%= content_tag( :div, flash[:warning]) %> in the application.html.erb file.
flash[:warning] = "Warning message!"
respond_to do |format|
format.html { redirect_to :root }
end
Why the flash[:warning] message is not displayed? How can I display that after redirection?
P.S. I: I tryed to use flash.keep[:warning] but that didn't work.
SOLUTION
The problem is that I am redirecting two times in my controller actions.
P.S. II: Who voted down can at least give some reasons...
flash.now[:key] will save flash message again key for one request try it
flash.now[:warning] ='message'
and then after redirection show warning message with
<%= flash.now[:warning] %>
Have you written this line in your layout/view? If not then write this code in your layout file
<%= flash[:warning] || flash[:notice] || flash[:alert] %>
I am currently using Devise to authenticate users on my app. It's working great for the most point, but I am having trouble with a specific action:
view:
<p id="save"><%= link_to "Save", new_save_path, :remote => true %></p>
saves_controller.rb:
def new
if user_signed_in?
#save = Save.create(:user_id => current_user.id)
render :update do |page|
page.replace_html "save", "Saved!"
end
else
redirect_to new_user_session_path, :notice => "You need to sign in to do that."
end
end
As you can see, because the action is an ajax one, I can't use the traditional before_filter :authenticate_user! method. So instead I am redirecting the user to the sign in page.
The problem is, I want to automatically redirect the user back to the previous page when they logged in.
I understand I can do this with the session[:"user.return_to"] but I'm having trouble setting it. How can I do this? Or am I going about this all wrong?
I believe the session key is :"#{scope}_return_to, which will be simply :user_return_to for a User class.