Parry Parry - 1 month ago 11
Ruby Question

Ruby on Rails - undefined method `errors' for nil:NilClass

This questions seems duplicate but I have checked all other related questions and none of the answers apply as I have tried them all.

I am trying to create a user signup form.

My user model (user.rb) is like this.

class User < ApplicationRecord
attr_accessor :password
EMAIL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i
validates :username, :presence => true, :uniqueness => true, :length => { :in => 4..20 }
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
validates :password, :confirmation => true #password_confirmation attr
validates_length_of :password, :in => 6..20, :on => :create
end


The user controller (users_controller.rb) is like this

class UsersController < ApplicationController

def new
@user = User.new
end

def create

@user = User.new(user_params)

if @user.save
flash[:notice] = "You have signed up successdully"
flash[:color] = "valid"
else
flash[:notice] = "Invalid Input!"
flash[:color] = "invalid"
end
end

def user_params
params.require(:username).permit(:email, :password, :password_confirmation)
end

render "new"

end


And the users new view (new.html.erb) is like this.

<% @page_title = "UserAuth | Signup" %>
<div class="Sign_Form">
<h1>Sign Up</h1>
<%= form_for(:user, :url => {:controller => 'users', :action => 'create'}) do |f| %>
<p> Username:</br> <%= f.text_field :username%> </p>
<p> Email:</br> <%= f.text_field :email%> </p>
<p> Password:</br> <%= f.password_field :password%></p>
<p> Password Confirmation:</br> <%= f.password_field :password_confirmation%> </p>
<%= f.submit :Signup %>
<% end %>
<% if @user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in @user.errors.full_messages %>
<li>* <%= message_error %></li>
<% end %>
</ul>
<% end %>
</div>


The routes (routes.rb) are like this

Rails.application.routes.draw do
get 'users/new'
resources :users

# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
root 'home#index'
end


And rake route gives me following output.

Prefix Verb URI Pattern Controller#Action
users_new GET /users/new(.:format) users#new
users GET /users(.:format) users#index
POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
edit_user GET /users/:id/edit(.:format) users#edit
user GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
root GET / home#index


Yet when I try to access http://localhost/users/new from my browser, I get the following error.

Showing C:/Sites/expenses/app/views/users/new.html.erb where line #11 raised:

undefined method `errors' for nil:NilClass
Extracted source (around line #11):
9
10
11
12
13
14

<%= f.submit :Signup %>
<% end %>
<% if @user.errors.any? %>
<ul class="Signup_Errors">
<% for message_error in @user.errors.full_messages %>
<li>* <%= message_error %></li>

Answer

Render new should be at the error in create.

This means that, if you have any error in the create action, the @user object is thrown back to the new form along with those errors

So there you can loop through those errors using @user.errors.any?

 class UsersController < ApplicationController

  def new
    @user = User.new
  end

  def create

    @user = User.new(user_params)

    if @user.save
        flash[:notice] = "You have signed up successdully"
        flash[:color] = "valid"
    else
        flash[:notice] = "Invalid Input!"
        flash[:color] = "invalid"
        render "new"
    end
  end

    def user_params
      params.require(:username).permit(:email, :password, :password_confirmation)
    end     
end