Ruby-on-rails NilClass:Class 的 Rails 未定义方法“model_name”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11093848/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:34:28  来源:igfitidea点击:

Rails undefined method `model_name' for NilClass:Class

ruby-on-railsrubyruby-on-rails-3

提问by Catfish

I have a form that i want to appear at the top of every page so i've included it in the /app/views/layouts/application.html.erb file and i get the error undefined methodmodel_name' for NilClass:Class` when trying to load the page.

我有一个表单,我undefined method想出现在每个页面的顶部,所以我将它包含在 /app/views/layouts/application.html.erb 文件中,并且在尝试时我收到了NilClass:Class`的错误model_name'加载页面。

Here's the form snippet in application.html.erb

这是 application.html.erb 中的表单片段

 <%= form_for @user do |f| %>
    <h3>Add new contact</h3>
    <%= f.text_field :first_name %><br />
    <%= f.text_field :last_name %>
    <%= f.text_field :email %>
    <hr />
    <%= f.submit "Add Contact" %>
<% end %>

Here's my /app/controllers/user_controller.rb

这是我的 /app/controllers/user_controller.rb

class UserController < ApplicationController

    def index

    end

    def new
        @user = User.new
    end

end

I'm thinking that i'm hitting this error because since the form is in the application.html.erb file, i need to somehow specify the path, but then again i'm very new to rails.

我在想我遇到了这个错误,因为由于表单在 application.html.erb 文件中,我需要以某种方式指定路径,但我对 rails 还是很陌生。

Let me know if you need anything else posted.

如果您需要发布任何其他内容,请告诉我。

EDITFollowing Ola's suggestion, In my app/views/layouts/application.html.erb file I have something like this:

编辑遵循 Ola 的建议,在我的 app/views/layouts/application.html.erb 文件中,我有这样的内容:

<div>
<%= yield :add_user %>
</div>

and in my app/views/users/new.html.erb file I have this

在我的 app/views/users/new.html.erb 文件中我有这个

<% content_for :add_user do %>
    <%= form_for @user do |f| %>
        <h3>Add new contact</h3>
        First Name<br />
        <%= f.text_field :first_name %><br />
        Last Name<br />
        <%= f.text_field :last_name %><br />
        Email<br />
        <%= f.text_field :email %>
        <hr />
        <%= f.submit "Add Contact" %>
    <% end %>
<% end %>

The form is not rendered because my url is http://localhost:3000/admin/indexand so it's looking for the add_usercontent_for in app/views/admin/index.html.erb

表单未呈现,因为我的 url 是http://localhost:3000/admin/index,所以它add_user在 app/views/admin/index.html.erb 中寻找content_for

回答by David J.

Did you try debugging first? I ask because you say you are new to Rails. If not, here is my approach. I want to share it, because I'm surprised how many people don't (for whatever reason) debug carefully.

您是否先尝试调试?我问是因为你说你是 Rails 的新手。如果没有,这是我的方法。我想分享它,因为我很惊讶有多少人(无论出于何种原因)没有仔细调试。

(I created a test app so that I could walk through your problem. First, I visited http://localhost:3000/users.)

(我创建了一个测试应用程序,以便我可以解决您的问题。首先,我访问了http://localhost:3000/users。)

First, look at the stack trace.

首先,查看堆栈跟踪。

NoMethodError in Users#index

Showing /Users/david/dev/testapp/app/views/layouts/application.html.erb where line #11 raised:

undefined method `model_name' for NilClass:Class Extracted source (around line #11):

用户中没有方法错误#index

显示第 11 行引发的 /Users/david/dev/testapp/app/views/layouts/application.html.erb:

NilClass:Class 提取源的未定义方法`model_name'(大约第 11 行):

8: </head>
9: <body>
10: 
11: <%= form_for @user do |f| %>
12:     <h3>Add new contact</h3>
13:     <%= f.text_field :first_name %><br />
14:     <%= f.text_field :last_name %>

This tells you line 11 in your code is the problem. Think -- what could be the issue? Routing is unlikely because you are just rendering the page. Not a syntax error, that would have triggered another error. Ok, so keep reading:

这告诉您代码中的第 11 行是问题所在。想想——可能是什么问题?路由不太可能,因为您只是在渲染页面。不是语法错误,那会触发另一个错误。好的,请继续阅读:

Rails.root: /Users/david/dev/testapp

Application Trace | Framework Trace | Full Trace

Rails.root:/Users/david/dev/testapp

应用程序跟踪 | 框架跟踪 | 完整跟踪

Now click "framework trace" and you will see:

现在单击“框架跟踪”,您将看到:

activemodel (3.2.6) lib/active_model/naming.rb:163:in model_name_from_record_or_class' activemodel (3.2.6) lib/active_model/naming.rb:158:inparam_key' actionpack (3.2.6) lib/action_view/helpers/form_helper.rb:369:in `form_for'

activemodel (3.2.6) lib/active_model/naming.rb:163:in model_name_from_record_or_class' activemodel (3.2.6) lib/active_model/naming.rb:158:inparam_key' actionpack (3.2.6) lib/action_view/helpers/form_helper.rb:369:in `form_for'

You may not understand all this -- few people do -- but you will see the error comes from model_name_from_record_or_classwhich comes from param_keywhich comes from form_for. That is a big clue!

您可能不了解所有这些——很少有人了解——但您会看到错误来自model_name_from_record_or_class哪个来自param_key哪个来自哪个form_for。这是一个很大的线索!

I recommend the use of the open_gemgem to make it easy to dig into source code:

我建议使用open_gemgem 来轻松挖掘源代码:

gem install open_gem

Now, take a look at activemodel, since it is the topmost gem in the stack trace:

现在,看看 activemodel,因为它是堆栈跟踪中最顶层的 gem:

gem open activemodel

Now, search for this with regular expression searching enabled:

现在,在启用正则表达式搜索的情况下搜索:

def .*model_name_from_record_or_class

def .*model_name_from_record_or_class

(Why? you want to find class methods -- e.g. definitions that start with selfas well.)

(为什么?你想找到类方法——例如同样以开头的定义self。)

This will take you to line 162 in naming.rb.

这将带您到第 162 行naming.rb

def self.model_name_from_record_or_class(record_or_class)
  (record_or_class.is_a?(Class) ? record_or_class : convert_to_model(record_or_class).class).model_name
end

Even without understanding all of this, it does give a big hint... the method tries to return the model name from the record or class. Why can't it? Because the parameter you are passing, @user, hasn't been set. The value of unset instance variables is nil, so it won't complain until you try to do something with it.

即使不了解所有这些,它也确实给出了一个重要提示……该方法尝试从记录或类中返回模型名称。为什么不能?因为您传递的参数@user, 尚未设置。unset 实例变量的值是 nil,所以它不会抱怨,直到你尝试用它做点什么。

I hope this helps for this question and for future ones.

我希望这对这个问题和未来的问题有所帮助。

回答by Ola Tuvesson

If the form is included for multiple actions (pages) you need to set @userto something or the form_fordirective will fail (it won't have anything to create a form for).

如果包括形式为多个操作(页),你需要设置@user的东西或form_for指令将失败(这不会有什么创建形式)。

A much better approach (and the Rails default) is to have separate views for each action, each including only the elements required by that action, and loaded into your application.html.erblayout with <%= yield %>. So you would have a app/views/users/new.html.erbview which has the form in it. You neververy rarely need to define any load paths in Rails, they are all derived from the model, controller and action names - or from your routes.rb. This is a core part of the convention over configurationparadigm which runs so deep in Rails.

一个更好的方法(以及 Rails 默认)是为每个操作设置单独的视图,每个视图只包含该操作所需的元素,并application.html.erb使用<%= yield %>. 所以你会有一个app/views/users/new.html.erb包含表单的视图。你从来很少需要定义Rails的任何负载路径,他们都是从模型,控制器和动作名称派生-或你的routes.rb。这是在 Rails 中深入运行的约定优于配置范式的核心部分。

Edit:If you doneed to have a form for creating a new object on every page (often used for UserSessions for example), you can rewrite your form_forso that it doesn't depend on an object being present:

编辑:如果您确实需要有一个表单来在每个页面上创建一个新对象(例如,通常用于 UserSessions),您可以重写您的表单form_for,使其不依赖于存在的对象:

form_for(User.new)

or if you need to force it to post to the createmethod

或者如果您需要强制它发布到create方法

form_for(User.new, :url => { :action => "create" }) 

You can read more about resource driven form_forin the Ruby On Rails API docs.

您可以form_forRuby On Rails API 文档中阅读有关资源驱动的更多信息

回答by Colin R

This answer is really just Someth's answer corrected, but the solution is to set @userfor every controller action, not just those pertaining to a specific controller. This can be done by using a before_filterin the ApplicationController, i.e.

这个答案实际上只是 Someth 的答案更正了,但解决方案是@user为每个控制器操作设置,而不仅仅是那些与特定控制器有关的操作。这可以通过before_filter在 ApplicationController 中使用 a 来完成,即

class ApplicationController < ActionController::Base
  before_filter :initialize_user

  def initialize_user
    @user = User.new
  end
end

ORby creating a new model in the form_for helper itself (note: this is ugly in terms of separation of concerns, but it works...)

或者通过在 form_for 助手本身中创建一个新模型(注意:这在关注点分离方面很丑陋,但它有效......)

 <%= form_for User.new do |f| %>
   <h3>Add new contact</h3>
   <%= f.text_field :first_name %><br />
   <%= f.text_field :last_name %>
   <%= f.text_field :email %>
   <hr />
   <%= f.submit "Add Contact" %>
 <% end %>

回答by Luillyfe

in the usercontroller:

在用户控制器中:

def index
   @user = User.new
end

回答by Someth Victory

Your problem is you are trying to add form to every action on your page, but didn't initialize user in all action. Try to initialize user in all actions:

您的问题是您正在尝试为页面上的每个操作添加表单,但没有在所有操作中初始化用户。尝试在所有操作中初始化用户:

class UserController < ApplicationController
    before_filter :initialize_user

    def index

    end

    def initialize_user
        @user = User.new
    end

end