嵌套模型validation – 不显示错误

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

我有一个有很多书的作者,如下:

作者:

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 

书:

 class Book < ActiveRecord::Base attr_accessible :name, :year belongs_to :author validates :name, :year, presence: true validates :year, numericality: { only_integer: true, less_than_or_equal_to: Time.now.year } end 

我创建了以下表单,以便在作者的作者中添加一本书#show:

   
#labels and buttons...

…使用以下authors_controller方法:

 def show @author = Author.find(params[:id]) @book = @author.books.build end 

…以及以下books_controller方法:

 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的例子,他们说应该有一个表格的实例变量而不是@ author.books.build,所以我把后者放在控制器和表中的@book中 – 仍无济于事。

谢谢你的帮助!

让我们一步一步。

您提交创建,然后输入您的创建操作

 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动作。

这使用了show模板,但没有调用show动作代码。 (旁注,也许新页面可能是更好的选择,因此用户可以尝试再次创建。)

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

你的节目模板呢

 if @book.errors.any? 

这将不会是真的,所以if中的其余模板将被跳过。 这就是没有错误的原因。

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

所以让我们切换到渲染新的。

 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 

你的新模板将是

 <% if @author.errors.any? %> 
    <% @author.errors.full_messages.each do |msg| %>
  • <%= msg %>
  • <% end %>
<% end %> <% if @book.errors.any? %>
    <% @book.errors.full_messages.each do |msg| %>
  • <%= msg %>
  • <% end %>
<% end %> <%= form_for([@author, @book], html: { class: "well" }) do |f| %> #labels and buttons... <% end %>

在Books controller /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 

如果作者不存在,则重定向到作者索引页面,并显示错误消息不要呈现新表单,因为您将无法构建书籍表单,因为作者是nil。

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

/books/new.html.erb

  <% if @book.errors.any? %> 
    <% @books.errors.full_messages.each do |msg| %>
  • <%= msg %>
  • <% end %>
<% end %>