对此有很多疑问,但似乎都没有帮助。是的,我看过this rails cast。
我的作者有很多书,如下:
作者:
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:
中为作者添加一本书<%= 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中的形式 - 仍无济于事。 / p>
感谢您的帮助!
答案 0 :(得分: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动作。
这使用了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? %>
<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 %>
答案 1 :(得分: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
如果作者不在场,则重定向到作者索引页面并显示错误消息不要呈现新表单,因为您将无法构建书籍表单,因为作者是nil。
在您的图书新表单中,您可以列出针对图书的错误
/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 %>