2010-09-24 5 views
63

Getting Started Rails Guide вид глянца над этой частью, так как он не реализует «новое» действие контроллера комментариев. В моем приложении, у меня есть модель книги, которая имеет много глав:Rails 3: Как создать новый вложенный ресурс?

class Book < ActiveRecord::Base 
    has_many :chapters 
end 

class Chapter < ActiveRecord::Base 
    belongs_to :book 
end 

В моих маршрутах ФАЙЛА:

resources :books do 
    resources :chapters 
end 

Теперь я хочу реализовать «новое» действие контроллера Chapters:

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 

Каков правильный способ сделать это? Кроме того, как выглядит сценарий вида (формы)?

ответ

119

Сначала вы должны найти соответствующую книгу в своем главном контроллере, чтобы построить для него главу. Вы можете сделать свои действия так:

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 

В вашей форме, new.html.erb

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

или вы можете попробовать стенографическую

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

Надеется, что это помогает.

+4

Для рефакторинга кода - также можно использовать метод get_book, чтобы найти книгу @book = Book.find (params [: book_id]), а затем использовать этот метод как фильтр before. Это связано с тем, что для любого метода, который вы реализуете в контроллере главы, нужен объект книги, к которому он принадлежит. – Ninad

+0

Re: комментарий выше, если у вас было несколько детей книги, вы бы реорганизовали метод get_book в 'BookHelper' и' include BookHelper' в вашем контроллере книг и контролерах, связанных с книгами. – ocodo

+0

Это не создает дополнительный запрос select для db? –

6

Пробег: @chapter = @book.build_chapter. Когда вы звоните @book.chapter, это нуль. Вы не можете сделать nil.new.

EDIT: Я только что понял, что книга, скорее всего, имеет несколько глав ... выше для has_one. Вы должны использовать @chapter = @book.chapters.build. Главы «пустой массив» на самом деле являются специальным объектом, который отвечает на build для добавления новых ассоциаций.

1

Возможно, несвязанный, но из названия этого вопроса вы можете приехать сюда, чтобы узнать, как сделать что-то немного другое.

Допустим, вы хотите сделать Book.new(name: 'FooBar', author: 'SO') и вы хотите разделить некоторые метаданные в отдельную модель, названная readable_config, которая является полиморфным и сохраняет name и author для нескольких моделей.

Как вы принимаете Book.new(name: 'FooBar', author: 'SO') построить Book модели и также readable_config модели (я бы, возможно, по ошибке, вызовите «вложенную ресурс»)

Это может быть сделано, как так:

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

Удивительно, мне нравится это решение, спасибо! – sidney

Смежные вопросы