Background
I'm implementing a feature in my application that allow users to rate and review pictures.
My problem stems from nesting Reviews resources inside Pictures resources, specifically in my Review#Edit function. The error message specifically declares missing required keys: [:id]
Error Message
ActionController::URLGenerationError in Reviews#Edit
No route matches {:action=>"show", :controller=>"reviews", :format=>nil, :picture_id=>#<Review id: 4, username: "DarkMouse", body: "Updating review", picture_id: 11, created_at: "2014-08-14 03:26:52", updated_at: "2014-08-14 03:55:29">, :id=>nil} missing required keys: [:id]
Undefined method 'reviews_path' for #<#<Class:0x45c1b00>:0x39ae810>
Extracted source (Around line #7):
4 <div class = 'center'>
5 <div class = 'center'>
6
7 <% form_for [:picture, @review] do |f| %>
8
9 <p>
10 <%= f.label :username, :class => 'marker' %><br />
I searched for answers on Stack Overflow.com(My references are given at the bottom) and was advised to do this.
<td><%= link_to 'Edit', edit_picture_review_path(@picture, review) %></td>
Every single solution I came across said to edit the path to include the specific object. If this is any indication, it looks like it really should work.
Parameters
{"picture_id"=>"11",
"id"=>"4"}
Also, my path_url is as follows
http://localhost:3000/pictures/11/reviews/4/edit
The URL path looks similar to my defined routes as well
edit_picture_review_path GET /pictures/:picture_id/reviews/:id/edit(.:format) reviews#edit
I am using a Posts/Comments relationship model for a Pictures/Reviews relationship.
Models
class Review < ActiveRecord::Base
belongs_to :picture
end
class Picture < ActiveRecord::Base
has_many :reviews
end
Above, I established a one-to-many relationship between pictures and reviews.
Routes
favorite_picture_path PUT /pictures/:id/favorite(.:format) pictures#favorite
picture_reviews_pat GET /pictures/:picture_id/reviews(.:format) reviews#index
POST /pictures/:picture_id/reviews(.:format) reviews#create
new_picture_review_path GET /pictures/:picture_id/reviews/new(.:format) reviews#new
edit_picture_review_path GET /pictures/:picture_id/reviews/:id/edit(.:format) reviews#edit
pictures_review_path GET /pictures/:picture_id/reviews/:id(.:format) reviews#show
PATCH /pictures/:picture_id/reviews/:id(.:format) reviews#update
PUT /pictures/:picture_id/reviews/:id(.:format) reviews#update
DELETE /pictures/:picture_id/reviews/:id(.:format) reviews#destroy
ReviewsController
class ReviewsController < ApplicationController
before_action :set_review, only: [:show, :edit, :update, :destroy]
before_filter :find_picture, only: [:index, :create, :edit, :update, :destroy]
def edit
@review = Review.find(params[:id])
end
def update
@review = Review.find(params[:id])
if @review.update_attributes(params[:review])
flash[:notice] = "Review updated"
redirect_to @picture
else
flash[:error] = "There was an error updating your review"
redirect_to @picture
end
end
private
def set_review
@review = Review.find(params[:id])
end
def find_picture
@picture = Picture.find(params[:picture_id])
end
def review_params
params.require(:review).permit(:username, :body, :post_id)
end
end
The problem might lie with the review_params
post_id #should be
review_id
Reviews#Index Page
<h3>Reviews for <%= "#{@picture.title}" %></h3>
<table class = "reviews-table">
<thead>
<tr>
<th>Review</th>
<th>Username</th>
<th><th>
</tr>
</thead>
<tbody>
<% @picture.reviews.each do |review| %>
<tr>
<td><%= review.body %></td>
<td><%= review.username %></td>
<td><%= link_to 'Edit', edit_picture_review_path(@picture, review) %></td>
</tr>
<% end %>
<div class = 'center'>
<p><%= link_to 'New Review', new_reviews_path(@review), :class => "btn btn-info" %></p>
<p><%= link_to 'Back', picture_path, :class => "btn btn-info" %></p>
</div>
Reviews#Edit Page
<h3>Edit Review</h3>
<div class = 'center'>
<div class = 'center'>
<%= form_for [:picture, @review] do |f| %>
<p>
<%= f.label :username, :class => 'marker' %><br />
<%= f.text_field :username %>
</p>
<p>
<%= f.label :body, "Review", :class => 'marker' %><br />
<%= f.text_area :body, :rows => "10", :cols => "10" %>
</p>
<p>
<%= f.submit "Submit Review", :class => 'btn btn-success' %>
</p>
<% end %>
routes.rb
resources :pictures do
put :favorite, on: :member
resources :reviews
end
As you can see above, I am using nested resources.
References and External Links
Missing required keys ActionController::UrlGenerationError missing required keys: [:id] No route matches missing required keys: [:id] ActionController::UrlGenerationError: missing required keys: [:id] No routes matches "missing required keys: [:id, :_id]"
All of the above links and more consulted. Every solution tried but none worked. This is why I am re-opening this question. I hope this guide can serve as a template for this problem moving forward.
Thanks in advance. This is not an easy question. Good luck.