0

To learn Rails, I'm working on a simple calendar app. To get started, I created two scaffolds and the proper associations/routes:

  • calendars
  • content_items

app/models/calendar.rb

class Calendar < ActiveRecord::Base
   has_many :content_items
end

app/models/content_item.rb

class ContentItem < ActiveRecord::Base
  belongs_to :calendar
end

routes.rb

resources :calendars do
  resources :content_items
end

controllers/content_items_controller.rb

 def create
   @content_item = ContentItem.new(content_item_params)
   @calendar = Calendar.find(params[:calendar_id] )
   respond_to do |format|
     if @content_item.save
       format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }
       format.json { render :show, status: :created, location: @content_item }
     else
       format.html { render :new }
       format.json { render json: @content_item.errors, status: :unprocessable_entity }
     end
   end
 end

When I created the nested routes, I began to run into errors when trying to create new content_items. Whenever I submit the form, I get this error:

NoMethodError in ContentItems#create
undefined method `content_items_path'

The error is coming from: views/content_items/index.html.erb

<%= form_for [@calendar, @content_item] do |f| %>

UPDATE Using the code posted below by @Gaurav GuptA fixed the form issue, but led to a new errror. Whenever I visit /calendars/1/content_items, I recieve an error - but only after creating an entry. With an empty database, it works fine.

ActionController::UrlGenerationError No route matches {:action=>"show", :calendar_id=>#, :controller=>"content_items", :format=>nil, :id=>nil} missing required keys: [:id]

I believe this is because the content_item is being saved without a calendar_id. How do I set the content_item to save with the calendar_id it belongs to?

UPDATE 2 It now saves with a calendar_id, but when an item is saved, the links for edit/shpw/destroy throw errors.

No route matches {:action=>"show", :calendar_id=>#<ContentItem id: 1, , content_type: "Test", content_text: "Tetst\r\n", calendar_id: 1, created_at: "2015-05-26 07:06:42", updated_at: "2015-05-26 07:06:42", content_image_file_name: nil, content_image_content_type: nil, content_image_file_size: nil, content_image_updated_at: nil>, :controller=>"content_items", :format=>nil, :id=>nil} missing required keys: [:id]

It highlights this part of the file:

<td><%= link_to 'Show', calendar_content_item_path(content_item) %></td>

GitHub link: https://github.com/JeremyEnglert/baked

JeremyE
  • 1,368
  • 4
  • 20
  • 40
  • I think issue is in this line "format.html { redirect_to @content_item, notice: 'Content item was successfully created.' }" of your create action in content_items_controller – Gaurav Gupta May 26 '15 at 04:33
  • can you update your question to include code of `ContentItems#create` and the output of `rake routes` in terminal – usmanali May 26 '15 at 05:23
  • Updated question above. – JeremyE May 26 '15 at 05:35
  • <%= link_to 'Show', calendar_content_item_path(content_item) %> change this to: <%= link_to 'Show', calendar_content_item_path(content_item.calendar_id, content_item.id) %> – Gaurav Gupta May 26 '15 at 07:21

2 Answers2

2

Try to change your create action of content_items_controller as:

 def create
   @calendar = Calendar.find(params[:calendar_id] )
   @content_item = @calendar.content_items.new(content_item_params) #Edit

   respond_to do |format|
     if @content_item.save
       format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }
       format.json { render :show, status: :created, location: @content_item }
     else
       format.html { render :new }
       format.json { render json: @content_item.errors, status: :unprocessable_entity }
     end
   end
 end

Hope this will work for you.

Gaurav Gupta
  • 1,181
  • 10
  • 15
  • Awesome - this fixed the form issue - huge thanks! I think the form is saving without a calendar_id, which leads to another error after saving the content. I updated the question above. – JeremyE May 26 '15 at 05:36
  • your show action path must be " /calendars/:calendar_id/content_items/:id", like '/calendars/1/content_items/23' – Gaurav Gupta May 26 '15 at 06:04
  • @GauravGupta, you are not saving the association therefore `@content_item` calendar_id is nil. Instead `@content_item = @calendar.content_items.build(params[:content])` – Cyzanfar May 26 '15 at 06:21
2

Ok so with the routes you have:

resources :calendars do
  resources :content_items
end

You get a path like this for example:

/calendars/50
/calendars/50/content_items/77

Which are then routed to:

app/controllers/calendars_controller.rb
app/controllers/content_items_controller.rb

Your error comes from your create action in your ContentItemsController. The params you are posting to the action include your calendar id "calendar_id"=>"1" but nothing is there to receive it. You need to get the instance of Calendar associated with the item you are creating.

@calendar = Calendar.find(params[:calendar_id] )

Then after you save @content_item pass to the calendar_content_item_path (as indicated in your routes) both objects:

format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }

In your create method in the ContentItemsController should look like this:

 def create
   @calendar = Calendar.find(params[:calendar_id] )
   @content_item = @calendar.content_items.build(params[:content])
   respond_to do |format|
     if @content_item.save
       format.html { redirect_to calendar_content_item_path(@calendar,@content_item), notice: 'Content item was successfully created.' }
       format.json { render :show, status: :created, location: @content_item }
     else
       format.html { render :new }
       format.json { render json: @content_item.errors, status: :unprocessable_entity }
     end
   end
 end

I have also noticed that you are passing the calendar id to your strong params. That would through an error since the calendar's id is not assigned by the user. You can read more on Strong Parameters.

Cyzanfar
  • 6,997
  • 9
  • 43
  • 81
  • This works great until I save an item. The items seem to be saving without a calendar_id, so I get an error when trying to view /calendars/1/content_items. I updated the original question with the new error I get after saving an item. – JeremyE May 26 '15 at 07:01