简体   繁体   English

了解Ruby on Rails:NoMethodError(nil:NilClass的未定义方法“ []”):

[英]Learn Ruby on Rails: NoMethodError (undefined method `[]' for nil:NilClass):

I am working through Daniel Kehoe's tutorial on rails and have run into a problem that I do not understand and cannot find an answer to online. 我正在研究Daniel Kehoe的Rails教程,遇到了一个我不了解并且找不到在线答案的问题。 I get the NoMethodError described in the title of this post when using a flash message with params. 当使用带参数的Flash消息时,我得到了本文标题中描述的NoMethodError。

Here is the controller 这是控制器

class ContactsController < ApplicationController

  def process_form
    Rails.logger.debug "DEBUG: params are #{params.inspect}"
    flash[:notice] = "Received request from #{params[:contact][:name]}"
    redirect_to root_path
  end
end

It works if I remove [:contact] and leave [:name]. 如果我删除[:contact]并保留[:name],它会起作用。 If I remove [:name] and leave [:contact] it redirects but doesn't display the name. 如果删除[:name]并保留[:contact],它将重定向但不显示名称。 If I have both [:contact] and [:name] as the controller listing shows I get the NoMethodError and it does not redirect. 如果我同时具有[:contact]和[:name],如控制器清单所示,则会收到NoMethodError,并且它不会重定向。

Here is my view page 这是我的查看页面

<% content_for :title do %>Contact<% end %>
<h3>Contact</h3>
<div class="form">
  <%= form_with( url: contact_path) do |form| %>
    <%= form.label :name %>
    <%= form.text_field :name, autofocus: true %>
    <br/>
    <br/>
    <%= form.label :email %>
    <%= form.email_field :email %>
    <br/>
    <br/>
    <%= form.label 'message' %>
    <%= form.text_area :content, size: '40x5' %>
    <br/>
    <br/>
    <%= form.submit 'Submit', class: 'submit' %>
  <% end %>
</div>

Here is my routes.rb 这是我的routes.rb

Rails.application.routes.draw do
  post 'contact', to: 'contacts#process_form'
  root to: 'visitors#new'
end

Here is my log when I get the NoMethodError : 这是我收到NoMethodError时的NoMethodError

Started POST "/contact" 2017-07-23 23:25:11 +0000 Processing by ContactsController#process_form as JS Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "name"=>"Jane Doe", "email"=>"jd@example.com", "content"=>"oiuwroiueroieroiuerw", "commit"=>"Submit"} DEBUG: params are "✓", "authenticity_token"=>"...", "name"=>"Jane Doe", "email"=>"jd@example.com", "content"=>"oiuwroiueroieroiuerw", "commit"=>"Submit", "controller"=>"contacts", "action"=>"process_form"} permitted: false> Completed 500 Internal Server Error in 3ms 已开始发布POST“ / contact” 2017-07-23 23:25:11 +0000由ContactsController#process_form作为JS处理:{“ utf8” =>“✓”,“ authenticity_token” =>“ ...”,“名称“ =>” Jane Doe“,”电子邮件“ =>” jd@example.com“,” content“ =>” oiuwroiueroieroiuerw“,” commit“ =>” Submit“}调试:参数为”✓“,” authenticity_token“ =>“ ...”,“名称” =>“ Jane Doe”,“电子邮件” =>“ jd@example.com”,“内容” =>“ oiuwroiueroieroiuerw”,“提交” =>“提交”,“ controller“ =>” contacts“,” action“ =>” process_form“}允许:false>在3毫秒内完成500 Internal Server Error

NoMethodError (undefined method `[]' for nil:NilClass): NoMethodError(nil:NilClass的未定义方法“ []”):

If you want to get values as object like params[:contact][:name] , you should specify the object to the form helper. 如果要将值作为对象获取,例如params[:contact][:name] ,则应将对象指定给表单助手。 Example using form_for helper: 使用form_for帮助器的示例:

<%= form_for(@contact) do |f| %>
    <div class="field">
        <%= f.label :name %><br>
        <%= f.text_field :name %>
    </div>
    <div class="field">
        <%= f.label :email %><br>
        <%= f.text_field :email %>
    </div>
    <div class="actions">
        <%= f.submit %>
    </div>
<% end %>

Here is a quick reference to see how to deal with objects in form: 这是快速参考,以了解如何处理表单中的对象:

http://guides.rubyonrails.org/form_helpers.html#binding-a-form-to-an-object http://guides.rubyonrails.org/form_helpers.html#binding-a-form-to-an-object

If you don't have any idea about how it works, i suggest you to generate the CRUD using the scaffold generator. 如果您对它的工作方式一无所知,建议您使用脚手架生成器生成CRUD。 Example: 例:

rails g scaffold Contact name:string email:string

This command will generate all files (controller, views) related to the CRUD. 该命令将生成与CRUD相关的所有文件(控制器,视图)。 So you can use this as reference. 因此,您可以以此为参考。 It will be already following the Rails convention. 它将已经遵循Rails约定。

Your params looks something like this 你的参数看起来像这样

params{
   :content => 'Words',
   :email => 'example.@gmail.com',
   :name => 'Joey Smith'
}

Side note, do you intend 'content' to be 'contact'? 旁注,您打算使“内容”成为“联系”吗?

Params is an object and this 参数是一个对象,这个

params[:contact][:name]

Would work if your params was structured like: 如果您的参数结构如下:

params {
      :contact => {
         :name => 'Joey Smith'
      }
}

Which it is not. 不是。

Not sure what you are trying to do because I don't see a 'contact' 不确定您要做什么,因为我看不到“联系人”

I would guess that what you want is 我想你想要的是

flash[:notice] = "Received request from #{params[:name]}"

form_with(url: contact_path) won't add the resource root to your inputs within the form rendered, take a look: form_with(url: contact_path)不会将资源根添加到呈现的表单中的输入中,请看一下:

<%= form_with(url: contact_path) do |form| %>
  <%= form.text_field :name %>
  ...
<% end %>

# Will give you
<form action="/contact" method="post" data-remote="true">
  <input type="text" name="name">
</form> 

And form_with(model: Model.new) : form_with(model: Model.new)

<%= form_with(model: Model.new) do |form| %>
  <%= form.text_field :name %>
<% end %>

# Will give you
<form action="/contact" method="post" data-remote="true">
 <input type="text" name="model[name]">
</form>

What you need is to pass the resource to be created, you should have a new method in your controller, and there create an instance variable which you can then use in the model option of your form_with . 您需要传递要创建的资源,控制器中应该有一个new方法,然后在其中创建一个实例变量,然后可以在form_withmodel选项中使用form_with

See also Unification of form_for and form_tag into form_with . 另请参见将form_for和form_tag统一为form_with

Since form_with is the "new standard" in Rails 5.1, I'd continue to use it. 由于form_with是Rails 5.1中的“新标准”,因此我将继续使用它。

To use form_with successfully, you have to use syntax like this: 要成功使用form_with ,必须使用如下语法:

<%= form_with scope: :post, url: posts_path do |form| %>
  <%= form.text_field :title %>
<% end %>

<%# Will generate %>

<form action="/posts" method="post" data-remote="true">
  <input type="text" name="post[title]">
</form>

Or this: 或这个:

<%= form_with model: Post.new do |form| %>
  <%= form.text_field :title %>
<% end %>

<%# Will generate %>

<form action="/posts" method="post" data-remote="true">
  <input type="text" name="post[title]">
</form>

For your particular situation, you should probably be doing something like this: 对于您的特定情况,您可能应该这样做:

<% content_for :title do %>Contact<% end %>
<h3>Contact</h3>
<div class="form">
  <%= form_with( scope: :contact, url: contact_path) do |form| %>
    <%= form.label :name %>
    <%= form.text_field :name, autofocus: true %>
    <br/>
    <br/>
    <%= form.label :email %>
    <%= form.email_field :email %>
    <br/>
    <br/>
    <%= form.label 'message' %>
    <%= form.text_area :content, size: '40x5' %>
    <br/>
    <br/>
    <%= form.submit 'Submit', class: 'submit' %>
  <% end %>
</div>

By doing this, it would modify the name of each input element from being content , email , name , etc to become contact[content] , contact[email] , contact[name] , etc. This would then allow your controller code to work. 通过这样做,它将把每个输入元素的名称从contentemailname等修改为contact[content]contact[email]contact[name]等。然后这将允许您的控制器代码起作用。

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

相关问题 Ruby On Rails - NoMethodError:nil:NilClass 的未定义方法“[]” - Ruby On Rails - NoMethodError: undefined method `[]' for nil:NilClass Ruby on Rails NoMethodError:nil:NilClass的未定义方法“ []” - Ruby on Rails NoMethodError: undefined method `[]' for nil:NilClass nil:NilClass Ruby on Rails的未定义方法&#39;&gt;&#39;(NoMethodError) - undefined method `>' for nil:NilClass Ruby on Rails (NoMethodError) nil 的未定义方法“%”:NilClass (NoMethodError) Ruby on Rails - Undefined method `%' for nil:NilClass (NoMethodError) Ruby on Rails Ruby on Rails 如何修复 NoMethodError: undefined method `id' for nil:NilClass - Ruby on Rails how to fix NoMethodError: undefined method `id' for nil:NilClass Rails 5.2 上的 Ruby - NoMethodError(nil:NilClass 的未定义方法“主机”): - Ruby on Rails 5.2 - NoMethodError (undefined method `host' for nil:NilClass): Ruby - NoMethodError(nil的未定义方法:NilClass): - Ruby - NoMethodError (undefined method for nil:NilClass): Ruby:NoMethodError:nil的未定义方法`&lt;&lt;&#39;:NilClass - Ruby: NoMethodError: undefined method `<<' for nil:NilClass undefined方法[]为nil:ruby中的NilClass(NoMethodError)...为什么? - undefined method [] for nil:NilClass (NoMethodError) in ruby… Why? Ruby未定义方法`[]&#39;表示nil:NilClass(NoMethodError)错误 - Ruby undefined method `[]' for nil:NilClass (NoMethodError) error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM