5

關於此問題有很多問題,但他們都沒有幫助。是的,我看過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 

我創建了下面的表格一本書添加到作者在作者#顯示:

<%= 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中的表單仍然無濟於事。

感謝您的幫助!

回答

8

讓我們一起來看看它。

您提交的創建,並進入你的創造行動

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動作代碼。 (附註,也許新的頁面將是一個更好的選擇,這樣用戶就可以再次嘗試創建。)

此時@author進行實例化,你找到了作者,但不@book。所以@book,如果被調用將是零。

你的節目模板確實

if @book.errors.any? 

這不會是真的,所以裏面的模板的其餘部分,如果將​​被跳過。這就是爲什麼沒有錯誤。

您不需要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 %> 
+0

感謝您已經是這個詳細的回答錯誤!我在書籍控制器中沒有新的方法 - 顯示作者時會顯示新書的表單。此外,當我按照您的建議更改書籍#create方法時,出現路由錯誤,指出找不到編輯方法。爲了解決這個問題,我需要採取什麼不同的措施? – weltschmerz

+0

我忘了將重定向改爲:new。正如我所描述的那樣,標準的RESTful設計(不一定是最好的設計),那裏將有一個新的書籍頁面。如果您希望以不同的方式運作,請嘗試瞭解發生了什麼問題,然後按照您的要求進行修復。 –

1

在書籍控制器 /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 %>