I\'m using rails 4.2
I have a helper file called devise_helper.rb
module DeviseHelper
def devise_error_messages!
return \"\" if resource
When you ran devise:install
(or something similar), it must have created views with some specific line of codes to display these messages.
If you look at this link, they explain that you can add <%= devise_error_messages! %>
in your views to display those error messages (which isn't really different from having a generic <% flash.each {...} %>
somewhere in your HTML...)
Most likely, the views related to sessions do not contain this line of code.
For newer version of Rails/Devise I recommend:
Instead of <%= devise_error_messages! %>
do:
<% if flash[:alert] %>
<%= flash[:alert] %>
<% end %>
Your test may look something like this (note, you must make this a 'feature' functional test to have access to the "page" variable):
RSpec.feature 'Sign In', :type => :feature do
describe "correct error message w/ wrong password" do
before :each do
@user = create(:user)
@user.confirm
visit new_user_session_path
fill_in "user_email", with: @user.email
fill_in "user_password", with: "wrongpassword"
click_button "Log in"
end
it "tells user on page 'Invalid Email or password'" do
expect(page).to have_text("Invalid Email or password")
end
end
end
I like this way. The HTML part is kind of original though.
I do not want to separate displaying error messages about authentication. So, I'm using this way.
module DeviseHelper
def devise_error_messages!
flash_alerts = []
if !flash.empty?
flash_alerts.push(flash[:error]) if flash[:error]
flash_alerts.push(flash[:alert]) if flash[:alert]
flash_alerts.push(flash[:notice]) if flash[:notice]
sentence = I18n.t("devise.failure.invalid") #=> "Invalid email or password."
else
sentence = I18n.t("errors.messages.not_saved",
count: resource.errors.count,
resource: resource.class.model_name.human.downcase)
end
return "" if resource.errors.empty? && flash_alerts.empty?
errors = resource.errors.empty? ? flash_alerts : resource.errors.full_messages
messages = errors.map { |msg| content_tag(:li, msg) }.join
html = <<-HTML
<div class="alert alert-danger">
<div id="error_explanation">
<strong>#{sentence}</strong>
<ul class="m-b-0 p-l-30 ">#{messages}</ul>
</div>
</div>
HTML
html.html_safe
end
end
A login with blank/wrong fields does not trigger (your) validations on the model, and therefore won't show your validation errors !
if you debug with byebug
(in the first line of your view for example), you'll notice
resource.errors.count # => 0
flash # => ....@flashes={"alert"=>"Invalid email or password."}
Devise populates the "alert flash" with specific sign in error messages unique to this context of sign-in.
Why do you not see all model validation error messages ? Because that wouldn't make sense : suppose your model has a mandatory :gender
attribute with validates_presence_of :gender
. If normal model errors were added, then you would also see "gender cannot be blank" in the list of errors when your user tries to sign in with a wrong login :oops:.
devise_error_messages!
is a specific devise method meant to show those specific errors. You can think of it as a partial validation on the fields that are used for sign in (and that are defined in your devise config file)
WORKAROUND :
If you really want to show all your error messages, you could just explicitely run the validations :
at the beginning of devise_error_messages!
resource.validate # It will generate errors and populate `resource.errors`
I believe it shouldn't mess up with other actions that already work well (register, etc.)