【问题标题】:Rails 4: Receiving the following error: First argument in form cannot contain nil or be emptyRails 4:收到以下错误:表单中的第一个参数不能包含 nil 或为空
【发布时间】:2015-08-14 21:21:29
【问题描述】:

我的一个项目收到以下错误:表单中的第一个参数不能包含 nil 或为空。我正在尝试为我的代码创建一个编辑页面。相当新的 Rails 并试图在没有脚手架的情况下学习。

控制器:

class BooksController < ApplicationController
def new
  @book = Book.new 
  @authors = Author.all
end

def edit 
  @book = Book.find(params[:id])  
end 

def show
 #Notice how the @books is plural here. 
 @books = Book.all
 @authors = Author.all
 #@books = Book.where(id: params[:id])
end 

#Create method will save new entries 
def create 
 @book = Book.new(book_params)
 @authors = Author.all

 if @book.save
    flash[:success] = "Book Added to Databse!"
    redirect_to @book  
  else
    render 'new'
  end 
 end 

 private 

 #Note that this method will go up into the create method above. 

 def book_params 
  params.require(:book).permit(:title, :pub_date, :publisher, :author_id)
 end 
end

模型页面:(用于书籍)

class Book < ActiveRecord::Base
  validates :title, :pub_date, :publisher, presence: true
  validates :title, uniqueness: true 
  belongs_to :author 
end

模型页面:(供作者)

class Author < ActiveRecord::Base
  validates :name, presence: true
  validates :name, uniqueness: true 
  has_many :books 
end

编辑页面:

<h1>Update a book entry</h2>

<div class="row">
 <div class="col-md-6 col-md-offset-3">

   <%= form_for(@book) do |f| %> **ERROR SEEMS TO BE RIGHT HERE!!!**
     <%= render 'form' %>

     <div class="form-group">
      <%= f.label :title %>
      <%= f.text_field :title, class: 'form-control' %>
     </div>

    <div class="form-group">
      <%= f.label :pub_date %>
      <%= f.text_field :pub_date, class: 'form-control' %>
    </div>

    <div class="form-group">
    <%= f.label :publisher %>
    <%= f.text_field :publisher, class: 'form-control' %><br />
  </div>

  <div class="form-group">
    <%= f.select(:author_id, 
    @authors.collect {|a| [ a.name, a.id ]},              
    {:include_blank => 'Please select an author'}, 
    class: "form-control") %><br />
  </div>

   <%= f.submit 'Save Changes', class: "btn btn-primary" %> 

  <% end %>
 </div>
</div>

渲染表单页面(_form.html.erb)

  <% if @book.errors.any? %>
   <div id="error_explanation">
    <div class="alert alert-danger">
     <h2><%= pluralize(@book.errors.count, "error") %> 
   prohibited this entry       from being saved:</h2>
   <ul>
   <% @book.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
  </ul>
  </div>


  </div>
 <% end %>

显示页面:

    <div class="move">
   <h1>Showing Book Titles:</h1>
  </div><br />

 <div class="row">
  <% @books.each do |book| %>
  <div class="col-md-4">
    <div class="panel panel-default">
        <div class="panel-body">
            <h2><%= book.title %></h2> 
            <h2><%= book.publisher %></h2>
            <h2><%= book.pub_date %></h2>
            <h2><%= book.author.name %></h2>
            <h2><%= link_to "Edit", edit_path, class: "btn btn-primary" %>
        </div>
    </div>
</div>
<% end %>

这是我的日志,告诉我出了什么问题:

Started GET "/edit" for ::1 at 2015-08-14 16:49:17 -0400
Processing by BooksController#edit as HTML
  Rendered books/edit.html.erb within layouts/application (2.2ms)
Completed 500 Internal Server Error in 9ms (ActiveRecord: 0.0ms)

ActionView::Template::Error (First argument in form cannot contain nil or be empty):
    3: <div class="row">
    4:   <div class="col-md-6 col-md-offset-3">
    5: 
    6:     <%= form_for(@book) do |f| %>
    7:       <%= render 'form' %>
    8: 
    9:       <div class="form-group">
  app/views/books/edit.html.erb:6:in `_app_views_books_edit_html_erb___525891009649529081_70260522100960'

我会说我已经从我的数据库中删除了前 14 本书,因此第一本书从 ID 14 开始。不确定这是否重要。

最后,我尝试在编辑方法中将所有这些不同的实例变量添加到我的控制器中:

   #@book = Book.where(id: params[:id])
   #@book = Book.find_by_id(params[:id])
   #@book = Book.all 
   #@book = Book.find_by_id(params[:id])
   #book = Book.new(book_params)

   #When I use the two below lines, 
  there are no error pages but create a new   entry. 
  #@book = Book.new 
  #@authors = Author.all

任何帮助将不胜感激!谢谢你的时间!!!

【问题讨论】:

  • 您要编辑的书可能不在您的数据库中。您的 URL 中的图书 ID 是什么?你确定那本书存在于你的数据库中吗?您可以通过 Rails 控制台确认。
  • 在我添加编辑功能之前,我的数据库中确实有书籍。添加编辑功能后,我删除了书籍,然后添加了一本。 (这将是一本 ID 为 14 的书。它是数据库中唯一的一本书。我可以在我的显示页面上单击它的编辑按钮,这就是我得到死亡红页的时候!
  • 即使我刚刚添加了一本新书,我也会收到以下错误消息:单击编辑按钮时找不到具有 'id'=id 的书。变得令人沮丧,但也是学习痛苦的一部分!
  • 如果你使用rake routes 来查看你的路线,你应该有一个像edit/:id 这样的。因此,如果您的数据库中存在 id 为 14 的书,您应该能够导航到 www.example.com/edit/14。另外,您是否发布了包含编辑书籍按钮的显示视图?如果没有,请发布,因为问题可能存在。
  • 我已经添加了上面的显示页面。当我前往localhost:3000/edit/14 时,我收到一条消息说没有路线匹配。我的显示页面中的这一行是否有误:

标签: ruby forms controller ruby-on-rails-4.2


【解决方案1】:

此错误意味着form_for 的第一个参数是nil 值(在本例中为@book)。大多数情况下,我都看到了这种情况,这是由于控制器操作格式错误,但这里的情况似乎并非如此。据我所知,这是两件事之一:

  1. 您正在尝试编辑不存在的图书。在决定呈现表单之前先检查.nil?,然后呈现错误消息(或重定向)。

  2. 您的路线已损坏,edit 操作未呈现 edit 视图。这很可能不是这种情况。

编辑:

使用show 的模板更新后,这看起来像是您的问题:

&lt;%= link_to "Edit", edit_path, class: "btn btn-primary" %&gt;

我发现这有两个问题(尽管我需要查看rake routes 的输出来验证)。首先,您需要将参数传递给编辑路径(没有它们,您的参数来自哪里?)。其次,默认路由是edit_book_path

试试这个:

&lt;%= link_to "Edit", edit_book_path(book), class: "btn btn-primary" %&gt;

【讨论】:

  • 不确定这是否正确,但确实如此: 仍然得到同样的错误。我同意我认为选项 2 不是问题。我认为你在做某事。我知道这本书在数据库中,但它只是没有把它拉起来。不过感谢您的帮助!
  • 在调用form_for 之前检查@book 是否为nil - 如果是,请不要调用form_for。相反,显示某种错误。我通常会检查它是否在控制器内为零,然后完全重定向到不同的页面。
  • 仍然收到错误消息找不到 Book with 'id'=id with @book.nil?
【解决方案2】:

假设图书 ID 14 在您的数据库中,如果您使用类似 resources :books(文档 here)的内容创建它,您应该能够导航到 localhost:3000/books/14/edit。如果这不起作用,则说明您的路线定义不正确,或者您的数据库中不存在 ID 为 14 的预订。

在您的显示视图中,将link_to 行更改为:

<%= link_to 'Edit', edit_book_path(book), class: "btn btn-primary" %>

所以有两个变化:

  1. 再次假设 book 是一个 Restful 资源,当您运行 rake_routes 时,您应该看到要编辑的路径是 edit_book_path
  2. 您需要将 book 实例与路径一起传递,以便 Rails 知道您要编辑哪个对象。

我找到了正确的语法here

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多