Home > OS >  Undefined method `errors' for nil:NilClass - when I click on Form Submit
Undefined method `errors' for nil:NilClass - when I click on Form Submit

Time:12-09

I have added validation to the form FORM. So whenever I click on the create employee with all the details it works but when I do not put the values I get this error. I have even changed to @employee in form_with.

I just want validations to be seen. How do I handle this?

Employees Controller:

class EmployeesController < ApplicationController
  before_action :set_employee, only: %i[ show edit update destroy]

  # GET /employees or /employees.json
  def index
    @employees = Employee.all
  end

  # GET /employees/1 or /employees/1.json
  def show
  end

  # GET /employees/new
  def new
    @employee = Employee.new
  end

  # GET /employees/1/edit
  def edit
  end

  # POST /employees or /employees.json
  def create
    employee_service = EmployeeCreationService.new(employee_params)

    respond_to do |format|
      if employee_service.execute!
        format.html { redirect_to employee_service.employee}
        # format.json { render :show, status: :created, location: @employee }
      else
        format.html { render :new, status: :unprocessable_entity }
        # format.json { render json: @employee.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /employees/1 or /employees/1.json
  def update
    respond_to do |format|
      if @employee.update(employee_params)
        format.html { redirect_to @employee}
        # format.json { render :show, status: :ok, location: @employee }
      else
        format.html { render :edit, status: :unprocessable_entity }
        # format.json { render json: @employee.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /employees/1 or /employees/1.json
  def destroy
    @employee.destroy
    respond_to do |format|
      format.html { redirect_to employees_url}
      # format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_employee
      @employee = Employee.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def employee_params
      params.require(:employee).permit(:name, :phone, :designation_id, :email, :password)
    end
end

Form:

<%= form_with(model: employee, local: true) do |form| %>
  <% if employee.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(employee.errors.count, "error") %> prohibited this employee from being saved:</h2>

      <ul>
      <% employee.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div >
    <%= form.label :name,class:"col-sm-2 col-form-label" %>
    <div >
    <%= form.text_field :name %>
    </div>
  </div>

  <div >
    <%= form.label :phone,class:"col-sm-2 col-form-label" %>
    <div >
    <%= form.text_field :phone %>
    </div>
  </div> 

 
 <div >
    <%= form.label :designation_id,class:"col-sm-2 col-form-label" %>
    <div >
    <%= form.select :designation_id, [["SOFTWARE ENGINEER", "2"], ["SERVICE ENGINEER", "3"]] %>
    
    </div>
  </div> 


  <div >
    <%= form.label :Email,class:"col-sm-2 col-form-label" %>
    <div >
    <%= email_field_tag 'employee[email]' %>
    </div>
  </div> 

   <div >
    <%= form.label :Password,class:"col-sm-2 col-form-label" %>
    <div >
    <%= password_field_tag 'employee[password]' %>
    </div>
  </div> 

<br />

  <div class='form-group'>
    <div >
      <h5 align="left">
      <%= form.submit class:"btn btn-dark"%>
      </h5></button>

    </div>
  <div >
    <div >&nbsp;
    <%= link_to 'Go Back', employees_path , class:"btn btn-primary btn-sm"%>
  </div>
  </div>
</div>
  

<% end %>

Service - to create employee and User simultaneously(Using Devise):

class EmployeeCreationService
    attr_reader :employee
    def initialize(employee_params)
        @employee_params = employee_params.except(:email, :password)
        @user_params = employee_params.slice(:email, :password)
    end

    def execute!
        begin
            @employee = Employee.create!(@employee_params)
            User.create!(@user_params.merge(employee: employee))
        rescue => exception
            @ex =  exception
            return false  
        end
        true
    end
end

CodePudding user response:

I suppose the problem in the create action in else branch of condition: The form needs that @employee variable should be set but it isn't for this case. You need to have the ability to have an instance of the Employee class from your service. Something like this:

@employee = employee_service.execute!
if @employee.valid?
  redirect_to
else
  render 

CodePudding user response:

  def create
    @employee = Employee.new(employee_valid)
    employee_service = EmployeeCreationService.new(employee_params)
    

    respond_to do |format|
      if employee_service.execute!
        format.html { redirect_to employee_service.employee}
        
      else
        format.html { render :new, status: :unprocessable_entity }
        
      end
    end
  end

Made these changes and it works fine now. For the validations, I have added JS.

Also slice employeee params with only the name phone and designation.

  • Related