Ruby on rails 嵌套模型验证-错误不';不显示

Ruby on rails 嵌套模型验证-错误不';不显示,ruby-on-rails,ruby,model-view-controller,validation,nested-forms,Ruby On Rails,Ruby,Model View Controller,Validation,Nested Forms,关于这一点有很多问题,但似乎都没有帮助。是的,我看过 我有一位作家,他有很多书,比如: 作者: class Author < ActiveRecord::Base attr_accessible :name has_many :books, dependent: :destroy accepts_nested_attributes_for :books, allow_destroy: true validates :name, presence: true vali

关于这一点有很多问题,但似乎都没有帮助。是的,我看过

我有一位作家,他有很多书,比如:

作者:

class Author < ActiveRecord::Base
  attr_accessible :name
  has_many :books, dependent: :destroy

  accepts_nested_attributes_for :books, allow_destroy: true

  validates :name, presence: true
  validates :name, length: { minimum: 3 }
end
…以及以下方法:

def show
    @author = Author.find(params[:id])
    @book = @author.books.build
end
def create
    @author = Author.find(params[:author_id])
    if @author.books.create(params[:book])
      redirect_to author_path(@author)
    else
      render action: :show
    end
  end
我似乎无法理解表单为什么不显示任何错误消息。我遵循railscasts的例子,他们说表单中应该有books的实例变量,而不是@author.books.build,所以我将后者放在控制器中,将@book放在表单中,但仍然没有用

谢谢你的帮助

让我们一步一步来

您提交了create,然后进入create操作

def create
  @author = Author.find(params[:author_id])
  if @author.books.create(params[:book])
    redirect_to author_path(@author)
  else
    render action: :show
  end
end
(旁注,如果找不到@author怎么办?你不是在处理这个案子。)

现在,找到了Author,但是@Author.books.create失败(返回false),因此呈现show操作

这将使用显示模板,但不调用显示操作代码。(请注意,新页面可能是更好的选择,因此用户可以尝试再次创建。)

此时@author被实例化为您找到的作者,但不是@book。所以@book,如果调用,将为零

您的显示模板不支持

if @book.errors.any?
这将不是真的,因此将跳过if中的其余模板。这就是为什么没有错误

您不需要表单_来显示错误消息。如果您切换到使用新模板,则将有一个表单重试

因此,让我们切换到渲染新对象

Class BooksController < ApplicationController
  def new
    @author = Author.find(params[:author_id])
    @book = @author.books.build
  end

  def create
    @author = Author.find(params[:author_id])
    @book = @author.books.build(params[:book])
    if @author.save
      redirect_to author_path(@author)
    else
      render action: :new
    end
  end
Class BooksController
您的新模板将被删除

<% if @author.errors.any? %>
    <div class="alert alert-block">
        <ul>
            <% @author.errors.full_messages.each do |msg| %>
                <li><%= msg %></li>
            <% end %>
        </ul>
    </div>
<% end %>
<% if @book.errors.any? %>
    <div class="alert alert-block">
        <ul>
            <% @book.errors.full_messages.each do |msg| %>
                <li><%= msg %></li>
            <% end %>
        </ul>
    </div>
<% end %>

<%= form_for([@author, @book], html: { class: "well" }) do |f| %>
#labels and buttons...
<% end %>

#标签和按钮。。。
在图书控制器中 /books_controller.rb

def new
   @author = Author.find_by_id(params[:author_id])
   @book = @author.books.build
end

def create 
   @author = Author.find_by_id(params[:author_id])
   if @author
     @book = @author.books.build(params[:book])
     if @book.save
       flash[:notice] = "Book saved successfully"
       redirect_to author_path(@author)
     else
       render :new
     end
  else
   flash[:notice] = "Sorry no author found"
   redirect_to author_path
  end 
end
如果作者不存在,请重定向到带有错误消息的作者索引页,不要呈现新表单,因为由于作者为零,您将无法构建图书表单

在您的图书新表单中,您可以为图书列出错误

/books/new.html.erb

  <% if @book.errors.any? %>
    <div class="alert alert-block">
      <ul>
         <% @books.errors.full_messages.each do |msg| %>
             <li><%= msg %></li>
         <% end %>
     </ul>
   </div>
 <% end %>


谢谢您的详细回答!我在books控制器中没有新方法-当显示作者时,将显示新书的表单。另外,当我按照您的建议更改books#create方法时,我收到一个路由错误,表示找不到编辑方法。要解决这个问题,我需要做哪些不同的操作?我忘记将重定向更改为:new。正如我所描述的,标准的RESTful设计(不一定是最好的设计)将为书籍提供一个新的页面。如果你想让它以不同的方式工作,试着去理解出了什么问题,并按照你想要的方式来修复它。
def new
   @author = Author.find_by_id(params[:author_id])
   @book = @author.books.build
end

def create 
   @author = Author.find_by_id(params[:author_id])
   if @author
     @book = @author.books.build(params[:book])
     if @book.save
       flash[:notice] = "Book saved successfully"
       redirect_to author_path(@author)
     else
       render :new
     end
  else
   flash[:notice] = "Sorry no author found"
   redirect_to author_path
  end 
end
  <% if @book.errors.any? %>
    <div class="alert alert-block">
      <ul>
         <% @books.errors.full_messages.each do |msg| %>
             <li><%= msg %></li>
         <% end %>
     </ul>
   </div>
 <% end %>