2017-07-24 40 views
1

我正在通过Daniel Kehoe的关于rails的教程进行工作,并遇到了一个我不明白的问题,并且无法找到在线答案。当使用带参数的flash消息时,我得到了这篇文章标题中描述的NoMethodError。学习Ruby on Rails:NoMethodError(未定义方法`[]'为零:NilClass):

这里是控制器

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 

如果我删除它的工作原理[:联系人],然后将[:名字]。如果我删除[:name]并离开[:contact],它将重定向但不显示名称。如果我在控制器列表中显示了[:contact]和[:name],我会得到NoM​​ethodError,并且它不会重定向。

这是我的看法

<% 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> 

这里是我的routes.rb

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

这是我的日志时,我得到了NoMethodError

开始POST“/接触“2017-07-23 23:25:11 +0000通过 处理ContactsController#process_form as JS参数:{”utf8“=>”✓“, “authenticity_token”=>“...”,“name”=>“Jane Doe”, “email”=>“[email protected]”,“content”=>“oiuwroiueroieieroiuerw”, “commit”=“ >“Submit”} DEBUG:params是“✓”,“authenticity_token”=>“...”,“name”=>“Jane Doe”, “email”=>“[email protected]”,“content “=>” oiuwroiueroieroiuerw”, “提交”=> “提交”, “控制器”=> “联系人”, “动作”=> “process_form”}允许:假>已完成在3ms的

500内部 服务器错误

NoMethodError(未定义的方法`[]”为无:NilClass):

回答

1

既然form_with是Rails 5.1中的“新标准”,我会继续使用它。

要成功使用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> 

或者这样:

<%= 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> 

对于您的具体情况,你可能应该做这样的事情:

<% 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> 

通过这样做,它会修改每个输入元素的名称t从content,email,name等变为contact[content],contact[email],contact[name]等,这将允许你的控制器代码工作。

+0

这解决了我的问题。谢谢。 – obx

1

如果你想获得价值作为像params[:contact][:name]这样的对象,您应该将对象指定给表单助手。使用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 %> 

这里是一个快速参考,看看如何处理在表单对象:

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

如果你没有它是如何工作的任何想法,我建议您使用脚手架生成器生成CRUD。例如:

rails g scaffold Contact name:string email:string 

该命令将生成与CRUD相关的所有文件(控制器,视图)。所以你可以用它作为参考。它将已经遵循Rails约定。

+0

谢谢加百列。只要我把这个格式放在parens中作为form_for(:contact,url:contact_path)就行了。 – obx

+0

好的兄弟,我很高兴你得到它的工作:) –

1

你PARAMS看起来像这样

params{ 
    :content => 'Words', 
    :email => '[email protected]', 
    :name => 'Joey Smith' 
} 

侧面说明,你打算“内容”是“接触”?

params为一个对象,如果你的PARAMS是结构类似这样的

params[:contact][:name] 

将工作:

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

它不是。

不知道你正在尝试做的,因为我没有看到一个“接触”

我猜想,你想要的是

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

form_with(url: contact_path)不会对资源root添加到呈现在表单中输入的,一起来看看:

<%= 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> 

而且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> 

你需要的是通过将要创建的资源,你应该有一个new方法在你的控制器,并有创建一个实例变量,然后您可以在您的form_withmodel选择使用。请参阅Unification of form_for and form_tag into form_with

相关问题