GaoVN
GaoVN

Reputation: 33

Getting undefined method `errors' for nil:NilClass on the view new

I'm new to ruby and i'm learning, so i was following this tutorial http://guides.rubyonrails.org/getting_started.html but when i try to add the error message i get undefined method `errors' for nil:NilClass at this piece of code:

<h1>New Article</h1>
     <%= form_for :posts, url: posts_path do |f| %>
      <% if @post.errors.any? %> // <-- **HERE**
          <div id="error_explanation">
            <h2>
              <%= pluralize(@post.errors.count, "error") %> prohibited

This is my controller:

class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def new
    @posts = Post.all
  end

  def create
      @posts = Post.new(posts_params)
    if @posts.save
        redirect_to @posts
    else
        render 'new'
    end
  end

  def show
    @posts = Post.find(params[:id])
  end

  private
  def posts_params
    params.require(:posts).permit(:title, :description)
  end  
end

This is my view that is giving me an error in full:

<h1>New Article</h1>
<%= form_for :posts, url: posts_path do |f| %>
<% if @post.errors.any? %>
    <div id="error_explanation">
      <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>
  <% end %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :description %><br>
    <%= f.text_area :description %>
  </p>

  <p>
    <%= f.submit %>
  </p>
<% end %>
<%= link_to 'Back', posts_path %>

My model: 



 class Post < ActiveRecord::Base

        validates :title, 
                :presence => {:message => "Title can't be blank." },
                :uniqueness => {:message => "Title already exists."},
                 length: { minimum: 5 }

        validates :description, 
        :presence =>{:message => "Description can't be blank." }
    end

Can someone help me?

Upvotes: 2

Views: 829

Answers (3)

Richard Peck
Richard Peck

Reputation: 76774

The error is that you've not declared @post

--

You need to do the following:

#app/controllers/posts_controller.rb
class PostsController < ApplicationController
   def new
       @post = Post.new
   end
end

#app/views/posts/new.html.erb
<%= form_for @post do |f| %>
   <% if @post.errors.any? %>
      ...
   <% end %>
   <%= f.submit %>
<% end %>

This will set the correct @post variable, which should give you the ability to call the .errors method on it.


As a sidenote,

undefined method `errors' for nil:NilClass

This error is often confused with new developers.

They think that their problem is errors method is missing; the real issue is that your variable is undeclared

Since Ruby is object orientated, it treats each variable as an object. Unlike other languages - which would raise exception based on the variable being undeclared, Ruby populates the nil:NilClass object.

Thus, whenever you see the above error, always remember that it means you've called a non-declared variable.

Upvotes: 0

chanakya devraj
chanakya devraj

Reputation: 148

I would like to suggest, just one thing :-

  • Since you are new to ruby please just try the convetional way to get the validation errors and displaying it as per the validations first, then you can go on experimenting the cause and other ways to get to the root cause.

you can try like :-

In controller

def new
 @post = Post.new
end 

and In your View

<%= form_for :post, url: posts_path do |f| %>
 <% if @post.errors.any? %>
 ---you code here --
 <% end %>
<% end %>

new action can be used to validate the params just before saving into the database hence calling some_obj = obj.new(params) and then som_obj.errors would definetly have the errors listed if valid params are not provided

Upvotes: 1

Geo
Geo

Reputation: 96767

You have the following:

<% if @post.errors.any? %>

but in your controller, you have:

 def new
    @posts = Post.new
  end

 def create
    @posts = Post.new(posts_params)
    ...
 end

Rename @posts to @post in your controller.

So, the code has to look like this:

def new
    @post = Post.new
  end

 def create
    @post = Post.new(posts_params)
    ...
 end

Upvotes: 2

Related Questions