Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is devise not displaying authentication errors on sign in page?

I'm using rails 4.2

I have a helper file called devise_helper.rb

module DeviseHelper
    def devise_error_messages!
        return "" if resource.errors.empty?

    messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
    sentence = I18n.t("errors.messages.not_saved",
                  count: resource.errors.count,
                  resource: resource.class.model_name.human.downcase)

     html = <<-HTML
     <div class="row">
     <div class="large-12 columns">
        <div data-alert class="alert-box alert radius">
          <h4>#{sentence}</h4>
          <ul>#{messages}</ul>
        </div>
     </div>
     </div>
     HTML
     html.html_safe
  end
end

to customize error messages and it's working for registrations and passwords pages, but not for sessions pages. Why is this? I know that I can add something like this:

  <div class="row">
    <% if notice %>
      <div data-alert class="alert-box info radius">
        <%= notice %><%= link_to "X", '#', :class => 'close' %>
      </div>
    <% end %>
    <% if alert %>
      <div data-alert class="alert-box alert radius">
        <%= alert %><%= link_to "X", '#', :class => 'close' %>
      </div>
    <% end %>
  </div>

To my application.html.erb file and error messages will display there, but I don't understand why I have to add that when I have the devise helper already. For the passwords and registrations, I just had to add <%= devise_error_messages! %> but the sessions pages don't seem to work that way. I'm not sure if this is just how devise works or if there's something I'm missing.

EDIT: I generated the sessions controller but I never changed anything in it since generating it. From what I understand, devise will just use its default controller until I change the one i generated. My passwords controller is like this as well. I did make some changes to the registrations controller to configure permitted parameters.

class Users::SessionsController < Devise::SessionsController

end
like image 269
WhyAyala Avatar asked Jul 13 '15 21:07

WhyAyala


People also ask

What is devise authentication?

Devise is an excellent authentication system made for Rails that allows us to easily drop-in User functionality into our project. Add Devise to your Gemfile and run bundle install. gem 'devise', '~> 3.4.0'


2 Answers

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.)

like image 174
Cyril Duchon-Doris Avatar answered Oct 29 '22 17:10

Cyril Duchon-Doris


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
like image 37
Henry Avatar answered Oct 29 '22 17:10

Henry