Reputation: 239057
The Getting Started Rails Guide kind of glosses over this part since it doesn't implement the "new" action of the Comments controller. In my application, I have a book model that has many chapters:
class Book < ActiveRecord::Base
has_many :chapters
end
class Chapter < ActiveRecord::Base
belongs_to :book
end
In my routes file:
resources :books do
resources :chapters
end
Now I want to implement the "new" action of the Chapters controller:
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
What is the right way to do this? Also, What should the view script (form) look like?
Upvotes: 66
Views: 36503
Reputation: 7909
First you have to find the respective book in your chapters controller to build a chapter for him. You can do your actions like this:
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 your form, new.html.erb
form_for(@chapter, :url=>book_chapters_path(@book)) do
.....rest is the same...
or you can try a shorthand
form_for([@book,@chapter]) do
...same...
Upvotes: 123
Reputation: 15249
Perhaps unrelated, but from this question's title you might arrive here looking for how to do something slightly different.
Lets say you want to do Book.new(name: 'FooBar', author: 'SO')
and you want to split some metadata into a separate model, called readable_config
which is polymorphic and stores name
and author
for multiple models.
How do you accept Book.new(name: 'FooBar', author: 'SO')
to build the Book
model and also the readable_config
model (which I would, perhaps mistakenly, call a 'nested resource')
This can be done as so:
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
Upvotes: 1
Reputation: 19249
Try @chapter = @book.build_chapter
. When you call @book.chapter
, it's nil. You can't do nil.new
.
EDIT: I just realized that book most likely has_many chapters... the above is for has_one. You should use @chapter = @book.chapters.build
. The chapters "empty array" is actually a special object that responds to build
for adding new associations.
Upvotes: 6