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

1

I've been trying to insert the alert into a form but I get 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 %>

In the error partition I have:

<% 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? %>

My controller already has:

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 the boss:

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

 end

And all the code is being rendered in the 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?

    
asked by anonymous 13.04.2014 / 21:43

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 this:

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

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

Update

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

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

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

def index
  @exercices = Exercice.all
end

Note that you do not have a @exercice , only a list of @exercices .

What I recommend you do:

  • Create the new.html.erb view in the app/views/exercices folder with the form in the same way as you did in the index view, including error checking. li>

  • Then remove the error checking on the form that is in the index view.

With "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:

So:

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 new view for validation errors. But if it uses the form in the index view, and there is no error, it will be redirected to the index view itself again.     

13.04.2014 / 23:12