2010-09-24 4 views
63

Die Getting Started Rails Guide Art von Glossen über dieses Teil, da es nicht die "neue" Aktion des Comments-Controllers implementiert. In meiner Anwendung habe ich ein Buch Modell, das viele Kapitel hat:Schienen 3: Wie erstellt man eine neue verschachtelte Ressource?

class Book < ActiveRecord::Base 
    has_many :chapters 
end 

class Chapter < ActiveRecord::Base 
    belongs_to :book 
end 

In meiner Routen-Datei:

resources :books do 
    resources :chapters 
end 

nun die "neue" Aktion des Chapters Controller implementieren Ich mag:

class ChaptersController < ApplicationController 
    respond_to :html, :xml, :json 

    # /books/1/chapters/new 
    def new 
    @chapter = # this is where I'm stuck 
    respond_with(@chapter) 
    end 

Was ist der richtige Weg? Wie sollte das View-Skript (Formular) aussehen?

Antwort

119

Zuerst müssen Sie das entsprechende Buch in Ihrem Kapitel Controller finden, um ein Kapitel für ihn zu erstellen.

class ChaptersController < ApplicationController 
    respond_to :html, :xml, :json 

    # /books/1/chapters/new 
    def new 
    @book = Book.find(params[:book_id]) 
    @chapter = @book.chapters.build 
    respond_with(@chapter) 
    end 

    def create 
    @book = Book.find(params[:book_id]) 
    @chapter = @book.chapters.build(params[:chapter]) 
    if @chapter.save 
    ... 
    end 
    end 
end 

In Ihrem Formular new.html.erb

form_for(@chapter, :url=>book_chapters_path(@book)) do 
    .....rest is the same... 

oder Sie können eine Kurz

form_for([@book,@chapter]) do 
    ...same... 

this helps versuchen: Sie können Ihre Aktionen wie dies tun.

+4

Zum Refactoring des Codes - man kann auch die get_book-Methode verwenden, um book @ book = Book.find (params [: book_id]) zu finden und diese Methode dann als Vorher-Filter zu verwenden. Dies liegt daran, dass jede Methode, die Sie im Kapitelcontroller implementieren, das Buchobjekt benötigt, zu dem sie gehört. – Ninad

+0

Re: Der Kommentar oben, wenn Sie mehrere Kinder des Buches hatten, würden Sie die "get_book" -Methode in 'BookHelper' und' include BookHelper' in Ihrem Bücher-Controller und Bücher bezogenen Controllern umgestalten. – ocodo

+0

Dies erstellt keine extra Select-Abfrage zu db? –

6

Versuchen Sie @chapter = @book.build_chapter. Wenn Sie @book.chapter aufrufen, ist es null. Sie können nil.new nicht tun.

BEARBEITEN: Ich habe gerade festgestellt, dass Buch wahrscheinlich has_many Kapitel hat ... das obige ist für has_one. Sie sollten @chapter = @book.chapters.build verwenden. Die Kapitel "leeres Array" ist eigentlich ein spezielles Objekt, das auf build reagiert, um neue Assoziationen hinzuzufügen.

1

Vielleicht nicht verwandt, aber aus dem Titel dieser Frage könnten Sie hier ankommen, um etwas anders zu machen.

Lassen Sie sagen Book.new(name: 'FooBar', author: 'SO') tun wollen, und Sie mögen einige Metadaten in ein eigenes Modell spalten, genannt readable_config die name und author für mehrere Modelle polymorpher und speichert ist.

Wie Sie Book.new(name: 'FooBar', author: 'SO') akzeptieren die Book Modell zu bauen und auch die readable_config Modell (was ich würde, vielleicht fälschlicherweise, rufen Sie eine ‚verschachtelte Ressource‘)

Dies als so getan werden kann:

class Book < ActiveRecord::Base 
    has_one :readable_config, dependent: :destroy, autosave: true, validate: true 
    delegate: :name, :name=, :author, :author=, :to => :readable_config 

    def readable_config 
    super ? super : build_readable_config 
    end 
end 
+0

Ganz erstaunlich, ich liebe diese Lösung, danke! – sidney