Ruby on rails flash notice error - ruby-on-rails

I have a problem with flash[:notice] = "Message" in Ruby on Rails.
I am trying to create login fault error message. My login fault handling is:
flash[:notice] = "Invalid username/password combination."
redirect_to(:action => 'login')
For the reason I don't know, alert just doesn't show up. I have red tons of possible solutions, but all of them just doesn't work for me. I am using Safari / Google Chrome web browsers.

Your controller code looks fine. I suspect your problem is not that you are calling the flash method incorrectly in your controller, but rather that you did not write the code (correctly) to display the flash in your view.
flash simply holds a message for your views to display. You are setting the message correctly, but you may not be displaying it properly. I can't tell because you aren't posting your view code.
For example, if this action is the result of submitting a user/login.html.erb form, based on your controller code, you would want to have the following code inside that view file:
<% flash.each do |key, value| %>
<div class="alert"><%= value %></div>
<% end %>
This code is a more basic version of what is described in this article.

Related

Why is my Flash.now not outputting after a render?

I have a minor issue I can't seem to figure out.
Regular flash works just as intended.
flash[:test] = 'Blarrgh'
redirect_to etcs_url
Will display 'Blarrgh' since I have this code in my application.html.erb
<% if flash[:test] %>
<%= flash[:test] %>
<% elsif flash.now[:test] %>
<%= flash.now[:test] %>
<% end %>
I'm pretty sure the way to display flash.now[:test] messages is just flash[:test], but I added the elsif in the bottom just in case since things weren't working.
For some reason, when I do
flash.now[:test] = 'Blarrgh'
render :edit
Nothing shows up at all. But when I put a 'fail' statement into my view then check out the values, flash[:test]/flash.now[:test] will have the proper values. E.g, ['Etc can't be blank']
I tried checking out common errors: no CSRF token, hidden redirect, flash.now b4 render, using form_with without local:true, but looking at my logs, there's no such issue. I included the CSRF token and my log path is
In logs:
patch /etc/1
(Commit fails, rolls back)
renders application.html.erb which yields etcs/edit.html.erb which renders etcs/_form.html.erb, then renders rest of etcs/edit.html.erb
And I'm putting my flash.now b4 the render. I'm also not using Rails helper functions like form_with.
Never mind, I figured it out. Rails is absolutely insane sometimes, apparently.
If you do a
Flash.now[:errors] = 'This is an error'
render :edit
This won't work. You have to do
Flash.now[:errors] = 'This is an error'
render :edit, status: :whatever_status
This doesn't show up as an error in the browser console, for some reason. It just simply doesn't display your flash.now. Supposedly, it's an issue with Rails 7's turbo being demanding as hell. I hope this saves someone from dealing with an awful lot of pain and misery.
Found the answer from Alex's reply in Flash is not displayed in the same view in Rails

Rails 6 prompt to download on mobile

I have a Rails 6 app where users can submit changes to a model and a confirmation email will be sent to site admins. The changes are submitted through a modal popup and once submitted the popup is replaced with another that confirms that the email has been sent.
The problem I am having is when this is done on a mobile device (I'm using an iPhone, not sure if this happens on Android), once the change is submitted another popup appears prompting me to download a file of size 0 with the name of the model being updated (it happens in both Safari and Chrome). This doesn't happen on the desktop version of the site or in the mobile emulator on the desktop, so I can't think of how I could diagnose this issue.
Here is the code being called just before the download popup appears:
<%= button_tag "Submit", type: 'submit',
id: 'modal-subimt',
class: 'btn btn-primary',
onClick: 'replaceModal()' %>
Here is the create function being called when the form is submitted:
def create
... # Setting the parameters for the model being changed
if #model.save
#model.send_confirmation_email()
else
# Irrelevant because the email gets sent
end
end
Here is the send_confirmation_email function being called in create:
def send_confirmation_email()
UserMailer.model_confirmation(self).deliver_now
end
And here is the model_confirmation function being called by send_confirmation_email:
def model_confirmation(model)
#model = model
recipient = <admin email>
mail to: recipient, subject: "Model Confirmation"
end
Nowhere in this code can I see where I might be prompted to download a file, but alas it is happening. Any help would be appreciated on how to properly diagnose or solve this problem. Thanks!
EDIT:
I changed my code so that the model would be updated without sending a confirmation email Also, the modal is no longer replaced with the new one verifying an email has been sent, and I am still having the same issue. This leads me to believe that the problem is something with the creation of the model.
EDIT 2:
Previously I was creating the model and remaining on the page (with the confirmation that the email was sent). I changed my controller to redirect_to request.referer to reload the page once the change is made, and when that is done I am no longer prompted to download the empty file. Unfortunately, the way I want this to work, reloading the page isn't optimal. Is there any reason that I would be prompted for a download when updating a model without reloading the page?
SOLUTION:
I was able to solve this problem by adding remote: true to the form_for line like the following:
<%= form_for(Model.new, remote: true) do |f| %>
...
<%= button_tag "Submit", type: 'submit',
id: 'modal-subimt',
class: 'btn btn-primary',
onClick: 'replaceModal()' %>
<% end %>
I'm not sure why exactly this solved my problem though so if anyone can provide some insight that would be much appreciated!
The problem is related to how you instantiated the form_for. When you submit the form to a Model.new object, form_for try to infer the controller with the create method for handling it. See more how form_for works in https://apidock.com/rails/ActionView/Helpers/FormHelper/form_for
With that said, the create method is probably outputting something or nothing instead of redirecting, that's why you get a download on a mobile device and in browsers it's just an empty page because they can handle it. If there is no render on the method, Rails will answer with a 204 No Content or an empty text page. You must check your method about this.
When you use remote: true, I will quote from the docs:
:remote - If set to true, will allow the Unobtrusive JavaScript drivers to control the submit behavior. By default this behavior is an ajax submit.
So instead of reloading the page, UJS sends a XMLHttpRequest to the "backend" page, that's why you don't get a redirect. The result of the submit is treated without redirecting. But based on the result of the request the content of the page can come. So it's important that you give a response accordingly. In the links below you will find the right way to do it.
See more in these questions:
How does ':remote => true' works in rails
:remote => true confusion with form_for
Also, in the Rails Guides:
https://guides.rubyonrails.org/form_helpers.html
https://guides.rubyonrails.org/working_with_javascript_in_rails.html
This is also a good reference:
http://www.korenlc.com/remote-true-in-rails-forms/

In Ruby (2.2) on Rails How Do I Have A Confirmation Box Pop Up Then Redirect To Another Page

In my controller I have an if condition and I want an alert/confirmation box to pop up if it is satisfied, then when the user clicks "ok" to redirect to another page.
I've tried
flash[:alert] = 'Successfully checked in'
redirect_to check_in_path
However it just skips the alert part and goes straight to the redirect without an alert message.
My Ruby version is ruby 2.2.6p396 and rails is 5.0.1
Any help would be appreciated
You need to create a js.erb file. You can then use your existing rails code along with a js alert box. Js.erb files let you combine rails and JavaScript code in the same file. As mentioned flash[:alert] is not an alert box, alert is a css class.
Rails is limited to the respond to HTTP request with HTML. And what you describe sounds more like a JavaScript alert. What you tried, if configured properly*, will simply show the flash alert when the check_in_path page is rendered.
* Get familiar with how the flash works, Rails Guides
You have your controller set up correctly. The only other part I meant by configured correctly is that in your views you should display said flash message:
<% flash.each do |name, msg| -%>
<%= content_tag :div, msg, class: name %>
<% end -%>
It's common to use the name of the flash to style it to make to make it's intent clear; commonly red for failure, green for success.
you can do it as follows
render :update do |page|
page << "alert('Successfully checked in')"
page.redirect_to check_in_path
end
but partial rendering in controller is most commonly used together with Ajax calls. so you may have to make an ajax call to your action from your view page. Hope this will help you

Rails - Devise sign in / authentication failure does not populate errors array with message

Using Rails 3.07 and Devise 1.1.5
Everything is working fine and as expected with one exception. When a user tries to login with a bogus password, for instance, devise denies the login attempt, which is correct, but fails to provide an error message.
I have several error display methods set up in app/helpers/devise_helper.rb and I am using one called devise_sign_in_error_messages! for the login view. Therefore I am able to verify that the following line from that function is returning a blank string for errors in this case:
return "" if resource.errors.empty?
If I give a correct username and password, the system logs me in just fine, so all of the devise logic seems fine, it's just this lack of an error message that's a mystery.
What do I need to change to help devise pass me an error message on failed login?
EDIT:
The answer is that:
a) devise is sticking the answer in flash
b) even though it's in flash, it's not using the key you might expect
Using this bit of code, I can see the message:
<% flash.each do |name, msg| %>
<%= content_tag :div, msg, :id => "flash_#{name}" if msg.is_a?(String) %>
<% end %>
Which I came across on a different post as an answer to a different question:
Another stack overflow post
I had tried to output the flash earlier but did not see the message because I followed a bit of code from a different stack overflow post that appears to be insufficient. Namely, I had tried:
<%= flash[:message] if flash[:message]
flash[:warning] if flash[:warning]
flash[:error] if flash[:error] %>
Devise is not using these keys for the login error message so this code will get you nothing.
I find devise's handling of this to be inconsistent. Specifically, if I choose devise's forgot password option and enter a bogus email address for instance, the error gets passed back in the resource.errors array, but here with the bad login it gets passed in flash.
As you have discovered Devise does not use flash[:message], flash[:warning], and flash[:error].
Devise uses flash[:notice] and flash[:alert].
It's not an easy find in the documentation but is just under the third point in Configuring controllers.
Hope this clears things up.

Flash messages in Rails getting carried over to the next page

I am displaying error and notice messages in my application with a helper method as shown below.
def display_flash_content
[:error, :notice].map do |key|
collection = flash[key].blank? ? [] : (flash[key].respond_to?(:map) ? flash[key] : [flash[key]])
collection.map {|item| content_tag(:div, item, :class => key.to_s) }
end
end
and my layout has this
<%= display_flash_content %>
I need to display these messages when I do some operation and then redirect to a specific page (this is working fine). But my problem is this flash message persists between pages. It's coming twice between pages where it needs to be cleared immediately once it's displayed to the user.
How to handle this scenario. Please help me!
The way you are displaying the flash messages is fine. I think the problem is how you are setting them. If you are setting flash messages and not redirecting you can assign to flash.now[:notice] instead of flash[:notice], for example, and your message will not hang around after the redirect.

Resources