简体   繁体   中英

NoMethodError in Rails app, method 'error' undefined

I am trying to create a Rails blog app with this tutorial

I am stuck on the step that validates that the fields a user enters are not empty. However, if I try to pass empty fields, I get this error:

NoMethodError in Posts#create
Showing C:/Users/irowe/Documents/GitHub/Rails-Blog/blog/app/views/posts/new.html.erb where line #3 raised:
undefined method `errors' for nil:NilClass

Here is my post controller:

class PostsController < ApplicationController
def index
  @posts = Post.all.order(created_at: :desc)
end
def show
end
def new
@post = Post.new
end
def create
  p = Post.new(title: params[:post][:title], content: params[:post][:content])
  if p.save
    flash[:notice] = 'Successfully created a new post!'
    redirect_to root_path
  else
    flash[:alert] = 'Something went awry...'
    render :new
  end
end
end

and my "new post" view

<h1>New Post</h1>
<ul>
  <% @post.errors.full_messages.each do |msg| %>
  <li><%= msg %></li>
  <% end %>
</ul>
<%= form_for @post, url: create_post_path do |f| %>
<%= f.text_field :title %>
<br />
<%= f.text_area :content %>
<br />
<%= f.submit %>
<% end %>

And the post model

class Post < ActiveRecord::Base
validates_presence_of :title
validates_presence_of :content
before_validation :preval
private
  def preval
  if self.title
    self.title = self.title.strip
  end
  if self.content
    self.content = self.content.strip
  end
end
end

I have seen other answers like this but they just recommend to make sure post is not nil , which I have made sure it isn't. Any ideas on how to make sure the validation woks? I am totally new to Rails.

You have to change your variable local into instances variable. To make instances variable, you can only add @ . It means the variable can be used in your new.html.erb file. For example:

def create
  @post = Post.new(title: params[:post][:title], content: params[:post][:content])
  if @post.save
    flash[:notice] = 'Successfully created a new post!'
    redirect_to root_path
  else
    flash[:alert] = 'Something went awry...'
    render :new
  end
end

This is good tutorial from rails guide rails guide to get started . I hope this tutorial can help you a lot.

NilClass

The error you're getting is standard if Rails is trying to manipulate an object which doesn't exist...

for nil:NilClass

For Ruby, there is no such thing as Nil - it translates it into a NilClass object. Thus, if you're trying to call the errors method on this object, it will raise an exception.

The error is with this line:

<% @post.errors.full_messages.each do |msg| %>

Now, this won't be the cause of the error, just the symptom. It means that @post doesn't exist. To remedy this, you need to look at why:

def create
  p = Post.new(title: params[:post][:title], content: params[:post][:content])
  if p.save
    flash[:notice] = 'Successfully created a new post!'
    redirect_to root_path
  else
    flash[:alert] = 'Something went awry...'
    render :new
  end
end

With this, you need to do several things:


Instance Variable

You need to make an instance variable , which will then be available in the view:

def create
  @post = Post.new post_params
  if @post.save

This should allow your view to access the @post variable (which it wouldn't do it it were just local in scope).

Conditional

Secondly, you may wish to make the errors invocation conditional:

<% if @post.errors.any? %>
   <% @post.errors.full_messages.each do |msg| %>

This should get it working for you.

The issue is in your create action. In it, you are using the local variable p to store the Post . However, when the validations fail, your code renders the new view. That view is looking for the instance variable @post . So simply, change your code to this:

@post = Post.new(title: params[:post][:title], content: params[:post][:content])
  if @post.save

I'm guessing you don't get the error when you open the new form, but only when you submit the form and it has errors.

That would be because you render the new form again here:

  flash[:alert] = 'Something went awry...'
  render :new

render simply renders the form, it does not redirect to the new action.
And you never set post in your create action.

An easy fix would be to change these two lines

p = Post.new(title: params[:post][:title], content: params[:post][:content])
if p.save

to this:

@post = Post.new(title: params[:post][:title], content: params[:post][:content])
if @post.save

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM