简体   繁体   English

Rails应用中的NoMethodError,方法“错误”未定义

[英]NoMethodError in Rails app, method 'error' undefined

I am trying to create a Rails blog app with this tutorial 我正在尝试通过本教程创建一个Rails博客应用

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. 我见过其他答案喜欢这个 ,但他们只是建议,以确保postnil ,这是我确定它是不是。 Any ideas on how to make sure the validation woks? 关于如何确保验证功能的任何想法? I am totally new to Rails. 我对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. 这意味着该变量可以在new.html.erb文件中使用。 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 . 这是从rails guide rails入门的好教程。 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... 如果Rails试图操纵一个不存在的对象,那么您得到的错误是标准错误。

for nil:NilClass

For Ruby, there is no such thing as Nil - it translates it into a NilClass object. 对于Ruby,没有Nil这样的东西-它会将其转换为NilClass对象。 Thus, if you're trying to call the errors method on this object, it will raise an exception. 因此,如果您尝试在此对象上调用errors方法,它将引发异常。

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. 这意味着@post不存在。 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). 这应该允许您的视图访问@post变量(它不会这样做,因为它只是作用域中的局部变量)。

Conditional 有条件的

Secondly, you may wish to make the errors invocation conditional: 其次,您可能希望使errors调用成为条件:

<% 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. 问题出在您的create操作中。 In it, you are using the local variable p to store the Post . 在其中,您正在使用局部变量p来存储Post However, when the validations fail, your code renders the new view. 但是,当验证失败时,您的代码将呈现new视图。 That view is looking for the instance variable @post . 该视图正在寻找实例变量@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. 我猜您在打开new表单时不会收到错误,而只是在提交表单时发现错误。

That would be because you render the new form again here: 那是因为您在这里再次渲染new表单:

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

render simply renders the form, it does not redirect to the new action. render仅呈现表单,它不会重定向到new操作。
And you never set post in your create action. 而且,您永远不会在create动作中设置post

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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