Search code examples
ruby-on-railsrubyformsmodelerror-messaging

Form Error Messages Not Generating in Rails App


Hi I have a simple app that I am building and am having trouble getting the error messages to appear when someone inputs invalid information or no information at all into a field.

The form I am using is to sign up a new user, the code associated with the user and form are below;

users_controller.rb

Class UsersController < ApplicationController


  def index
    @users = User.all
  end

  def show
    @user = User.find(params[:id])
    @country = Country.all
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)
    if @user.save
      session[:user_id] = @user.id
      redirect_to @user
    else
      redirect_to '/signup'
    end
  end


  private 

    def user_params
        params.require(:user).permit(:first_name, :last_name, :email, :password)
    end


end

user.rb

class User < ApplicationRecord

  before_save { self.email = email.downcase }
  validates :first_name, presence: true, length: { maximum: 25 }
  validates :first_name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 }, format: { with: VALID_EMAIL_REGEX }
  has_secure_password
  validates :password, presence: true, length: { minimum: 6 }

  has_many :trips
  has_many :countries, through: :trips

end

new.html.erb

<div class="container">
  <h1 class="text-center">Sign up</h1>
  <div class="row">
    <div class="col-md-6 offset-md-3 ">
      <%=form_for(@user) do |f| %>
        <%= render 'shared/error_messages' %>

        <%= f.label :first_name %>
        <%= f.text_field :first_name, class: "form-control" %>

        <%= f.label :last_name %>
        <%= f.text_field :last_name, class: "form-control" %>

        <%= f.label :email %>
        <%= f.email_field :email, class: "form-control" %>

        <%= f.label :password %>
        <%= f.password_field :password, class: "form-control" %>

        <%= f.submit "Create an account", class: 'form-control btn btn-primary' %>
      <% end %> 
    </div>
  </div>
</div>

_error_messages.html.erb

<% if @user.errors.any? %>
  <div class="alert alert-danger">
    The form contains <%= pluralize(@user.errors.count, "error") %>.
  </div>
  <ul>
  <% @user.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
  </ul>
<% else %>
  <h3>test</h3>
<% end %>

When I load the form I do see the "Test" string, which I put in my _error_messages.html.erb for visibility. However when I enter data in the signup page, it reloads the page (as it should rather than sending it to the user page when all fields are valid). However, the "Test" string still appears at the top rather than the error messages that should.

My assumption is I need some sort of session or something to remember what the errors were, as right now it reloads a completely new page with nothing in memory, however, I cannot find the solution to this anywhere at the moment.

Any help would be much appreciated!


Solution

  • As I said, you need to change

    redirect_to '/signup' 
    

    to

    render 'new'
    

    From the Guides

    The render method is used so that the @user object is passed back to the new template when it is rendered. This rendering is done within the same request as the form submission, whereas the redirect_to will tell the browser to issue another request.

    That said, so as the redirect_to issues a new request to the browser, the values of @user is lost, in other words @user is a new instance that is instantiated again. That is why <% if @user.errors.any? %> always returns false as if there are no errors in @user.