5

Es gab viele Fragen dazu, aber keine von ihnen scheint zu helfen. Und ja, ich habe mir this rails cast angesehen.Verschachtelte Modellvalidierung - Fehler werden nicht angezeigt

Ich habe einen Autor, der viele Bücher hat, etwa so:

Autor:

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 

Buch:

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 

ich das folgende Formular erstellt, ein Buch zu einem Autor hinzufügen in Autoren # zeigen:

<%= 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 %> 

... mit folgenden authors_controller Methode:

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

... und die folgende books_controller Methode:

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 

ich nicht scheinen, um herauszufinden, warum die Form keine Fehlermeldungen anzeigt. Ich folgte dem Beispiel von Railscasts, wo sie sagen, dass es eine Instanzvariable von Büchern in dem Formular geben sollte statt @ author.books.build, also habe ich letzteres in den Controller und @book in das Formular eingefügt - immer noch ohne Erfolg.

Vielen Dank für jede Hilfe!

Antwort

8

Lassen Sie uns durchgehen.

Sie senden das schaffen, und das geht die Aktion erstellen

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 

(Randbemerkung, was passiert, wenn @author nicht gefunden wird. Sie sind diesen Fall nicht handhaben.)

nun den Autor gefunden, aber @ author.books.create schlägt fehl (gibt false zurück), sodass Sie die show-Aktion rendern.

Dies verwendet die Show-Vorlage, ruft aber nicht den Show-Action-Code auf. (Seitennotiz, vielleicht wäre die neue Seite eine bessere Wahl, so dass der Benutzer versuchen kann, erneut zu erstellen.)

An diesem Punkt wird @author mit dem Autor instanziiert, den Sie gefunden haben, aber nicht @book. Also @book, wenn angerufen wird, wird Null sein.

Ihre Show-Vorlage tut

if @book.errors.any? 

, die nicht wahr sein, so dass der Rest der Schablone innerhalb der, wenn übersprungen. Deshalb gibt es keine Fehler.

Sie benötigen keine form_for, um Fehlermeldungen anzuzeigen. Wenn Sie zur Verwendung der neuen Vorlage wechseln, wird es ein Formular geben, um es erneut zu versuchen.

Lassen Sie uns zum Rendern wechseln.

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 

Die neue Vorlage

<% 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

bereits Sie für diese ausführliche Antwort danken aufgeführt haben kann! Ich habe keine neue Methode im Buch-Controller - das Formular für ein neues Buch wird angezeigt, wenn ein Autor angezeigt wird. Auch wenn ich die Methode books # create wie vorgeschlagen ändere, erhalte ich einen Routing-Fehler, der besagt, dass die Editiermethode nicht gefunden werden kann. Was muss ich anders machen, um das zu beheben? – weltschmerz

+0

Ich habe vergessen, die Weiterleitung zu ändern: neu. Das Standard RESTful Design (nicht unbedingt das beste Design) ist wie ich beschrieben habe, wo es eine neue Seite für Bücher geben würde. Wenn Sie es anders machen wollen, versuchen Sie zu verstehen, was schief gelaufen ist, und reparieren Sie es so, wie Sie es wollen. –

1

In Bücher 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 

Wenn Autor nicht vorhanden Umleitung Autoren Index-Seite mit Fehlermeldung wird nicht das machen neues Formular, da Sie nicht in der Lage sein werden, die Bücher Form als Autor zu erstellen ist Null.

Und in Ihrer Bücher neue Form Sie die Fehler für Bücher

/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 %> 
Verwandte Themen