I'll preface this by saying that I have read the duplicate questions. They seem to be pretty old, and their solutions have not worked.
I have the following code for a custom sign in form in views/devise/sessions/new.html.erb
:
<%= form_with model: resource, url: session_path(resource_name), as: resource_name do |form| %>
<%= form.text_field :email, class: "input" %>
<%= form.password_field :password, class: "input" %>
<%= tag.button(class: "btn-gradient input-button", type: "submit") do %>
<span>Sign In</span>
<% end %>
<% end %>
I am trying to pull errors and display them, and the following does not work:
<% if resource.errors.any? %>
<div class="error">
<% resource.errors.full_messages.each do |message| %>
- <%= message %></br>
<% end %>
</div>
<% end %>
I've tried a few other variants online, but it does not seem that any errors are caught. If I type an incorrect email password combination, nothing happens. I've used the same syntax in other forms (like creating or editing a model), and it works fine.
Not sure why it's different with a devise sign in.
How can I get errors in a devise form?
The speedrun explaination of how authentication in Devise works is that Devise::SessionsController#create
calls self.resource = warden.authenticate!(auth_options)
and if Warden cannot find a user with the given email/password it will throw(:warden). The throw is then caught by calling Devise::FailureApp
which redirects the user to the sign in path.
This is a more complex operation then your average scaffolded Rails controller that just renders the new view when the validations fail.
There are no errors on the resource
object because:
resource
in your form is not the same instance as when authentication was performed in a completely different request cycle.When Devise performs authentication fails it just sets a flash message which by default is "Invalid email or password."
. Remember that flash messages are passed through a cookie from one request to the next - model instances are not.
This is also the only feedback you should actually give. If you for example added a separate "Invalid email" message it lets an attacker performing a brute force attack determine if an email exists and you just made thier job a whole lot easier.
You can customize the flash messages simply by defining your own locale file and if you want to you can display the flash messages on the form.