Ruby on Rails - Undefined method `errors' for nil:Nilclass

Asked

Viewed 1,012 times

1

I have been trying to insert Alert in a form but I have the following error:

undefined method 'errors' for nil:NilClass

In my form I make a reference to the error:

<%= form_for :exercice do |f|%>
 <%= render 'erro' %>
 <%= f.label :timer, "Tempo" %>
 <%= f.number_field  :timer %>
 <%= f.label :category_id, "Categoria"%>
 <%= collection_select(:exercice, :category_id, Category.all, :id, :name,      prompt: "Selecione") %>
 <%= f.label :date, "Data"%>
 <%= f.date_select :date %>
 <%= f.submit class: "btn btn-large btn-success"%>
<% end %>

On partition have error:

<% if @exercice.errors.any? %>
  <div id="errorExplanation">
   <h2><%= pluralize(@post.errors.count, "error") %> prohibited
   this post from being saved:</h2>
   <ul>
    <% @post.errors.full_messages.each do |msg| %>
     <li><%= msg %></li>
    <% end %>
   </ul>
  </div>

In this case, the system is criticizing the line

<% @post.errors.any? %>

Already on my controller I have:

class ExercicesController < ApplicationController
 before_action :set_exercice, only: [:destroy]

 def index
  @exercices = Exercice.all
 end

 def new
  @exercice = Exercice.new
 end

 def create
  @exercice = Exercice.new(exercice_params)
  if @exercice.save
   redirect_to exercices_path
  else
    redirect_to exercices_path
  end
 end


 def destroy
  @exercice.destroy
  redirect_to exercices_url
 end

 private

  def set_exercice
    @exercice = Exercice.find(params[:id])
  end


  def exercice_params
    params.require(:exercice).permit( :timer, :date, :category_id)
  end

end

I created the routes as boss:

 Agenda::Application.routes.draw do
  resources :exercices

 end

And all the code is being rendered at index:

<div class="center hero-unit">
  <h1>Log de Exercícios</h1>
  <div class="form-inline">
   <%= render  "form" %>
  </div>
 <table class="table table-striped">
  <thead>
   <tr>
    <th>Tempo</th>
    <th>Categoria</th>
    <th>Data</th>
    <th></th>
    <th></th>
    <th></th>
  </tr>
 </thead>

<tbody>
  <% @exercices.each do |exercice| %>

      <tr>
        <td><%= exercice.timer %></td>
        <td><%= exercice.category.name %></td>
        <td><%= l exercice.date %></td>
        <td><%= link_to 'Excluir', exercice, method: :delete, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger btn-sm'%></td>
      </tr>
   <% end %>
</tbody>


Any suggestions?

1 answer

2

Instead:

def create
  @exercice = Exercice.new(exercice_params)
  if @exercice.save
    redirect_to exercices_path
  else
    redirect_to exercices_path
  end
end

Do it:

def create
  @exercice = Exercice.new(exercice_params)
  if @exercice.save
    redirect_to exercices_path
  else
    render :new
  end
end

In case of error you should not redirect, but just render the view new.


Updating

Good what is happening is that you are rendering the form in the view index, which includes the following code:

<% if @exercice.errors.any? %>
  (...)
<% end %>

The mistake undefined method 'errors' for nil:NilClass happens because there is no valid instance for the variable @exercice:

def index
  @exercices = Exercice.all
end

Notice how you don’t have one @exercice, only a list of @exercices.

What I recommend you do:

  • Create the view new.html.erb in the briefcase app/views/exercices with the identical form as you did in the view index, including checking for errors.

  • Then remove the error check in the form in the view index.

By "error checking" I mean this excerpt:

<% if @exercice.errors.any? %>
  (...)
<% end %>
  • And finally change the code of ExerciceController to render the view new in case of error when saving the object:

Thus:

def create
  @exercice = Exercice.new(exercice_params)
  if @exercice.save
    redirect_to exercices_path
  else
    render :new
  end
end

This will cause the user to remain in the view new as long as there are validation errors. But if it uses the form in the view index, and no error, it will be redirected to the view itself index again.

  • Hello @user3153542 Only that in my case I don’t have the New view, everything works in a single page, the index! That is, the path "form" is rendered in the index view. I created this action New I don’t even remember the same pq, because in the background I didn’t need, I think!

  • Good morning @user5476 It seems that you are not following the Rails conventions, which exist precisely to allow others Rails Developers understand your code more easily. Please edit your question including your routes.rb for me to take a look and I will try to edit my question with the solution.

  • Good morning @user3153542! I’ve changed my question :)

  • @user5476, also already edited my answer.

  • Sorry for the delay, I forgot. I understood what you said and I think it works, since that would be more code to keep up to date in the future and other, duplication is not always good. But I will try to implement here.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.