5

对此有很多问题,但似乎都没有帮助。是的,我看过这个铁轨演员

我有一个作者有很多书,像这样:

作者:

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

我创建了以下表单来将一本书添加到 authors#show 中的作者:

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

...使用以下 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 放在表单中 - 仍然无济于事。

谢谢你的帮助!

4

2 回答 2

9

让我们一步一步来。

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

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.books.create 失败(返回 false),因此您渲染了 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? %>
    <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 %>
于 2012-10-19T10:30:39.613 回答
1

在 Books 控制器 /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 %>
于 2012-10-19T14:53:25.463 回答