2010-09-24 20 views
63

El tipo Getting Started Rails Guide glosa esta parte ya que no implementa la "nueva" acción del controlador de comentarios. En mi solicitud, tengo un modelo de libro que tiene muchos capítulos:Rails 3: ¿Cómo crear un nuevo recurso anidado?

class Book < ActiveRecord::Base 
    has_many :chapters 
end 

class Chapter < ActiveRecord::Base 
    belongs_to :book 
end 

en mis rutas de archivos:

resources :books do 
    resources :chapters 
end 

Ahora quiero poner en práctica la "nueva" acción del controlador de Capítulos:

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 

¿Cuál es la forma correcta de hacerlo? Además, ¿a qué debería parecer el script de vista (formulario)?

Respuesta

119

Primero debes encontrar el libro respectivo en el controlador de tus capítulos para armar un capítulo para él. Usted puede hacer sus acciones como esta:

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 

En su formulario, new.html.erb

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

o puede probar una taquigrafía

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

Espero que esto ayude.

+4

Para refacturar el código, también se puede usar el método get_book para encontrar el libro @book = Book.find (params [: book_id]) y luego usar este método como filtro anterior. Esto se debe a que cualquier método que implemente en el controlador del capítulo necesitaría el objeto del libro al que pertenece. – Ninad

+0

Re: el comentario anterior, si tuviera varios hijos del libro, refactorizaría el método 'get_book' en' BookHelper' y 'include BookHelper' en el controlador de libros y en los controladores relacionados con libros. – ocodo

+0

¿Esto no crea una consulta de selección adicional a db? –

6

Probar @chapter = @book.build_chapter. Cuando llamas al @book.chapter, es nulo. No puede hacer nil.new.

EDIT: Me acabo de dar cuenta de que el libro probablemente tiene_muchos capítulos ... el anterior es para has_one. Debe usar @chapter = @book.chapters.build. Los capítulos "matriz vacía" es en realidad un objeto especial que responde al build para agregar nuevas asociaciones.

1

Quizás sin relación, pero a partir del título de esta pregunta puede llegar aquí buscando cómo hacer algo ligeramente diferente.

Digamos que usted quiere hacer Book.new(name: 'FooBar', author: 'SO') y desea dividir algunos metadatos en un modelo separado, llamado readable_config que es polimórfico y almacena name y author para varios modelos.

¿Cómo se acepta Book.new(name: 'FooBar', author: 'SO') para construir el modelo Book y también el modelo de readable_config (que yo, tal vez por error, llame a un 'recurso anidado')

Esto se puede hacer como tan:

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

Bastante sorprendente, me encanta esta solución, ¡gracias! – sidney

Cuestiones relacionadas