Reputation: 3100
I'm working on an app that allows users to comment on a single "work" (think blog post). The associations in the models are as follows:
class User < ActiveRecord::Base
has_many :works
has_many :comments
class Work < ActiveRecord::Base
belongs_to :user
has_many :comments
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
belongs_to :work
There's a form on the Works show page that allows users to post a comment:
<%= form_for(@comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Post a comment!" %>
</div>
<%= f.submit "Post", class: "btn btn-small btn-primary" %>
<% end %>
The Works controller is as follows. Note that I'm adding the build comment functionality here so that the form on the Works page functions:
class WorksController < ApplicationController
#before_filter :current_user, only: [:edit, :update]
def index
@works = Work.all
@comment = @work.comments.build(params[:comment])
@comment.user = current_user
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @works }
end
end
def create
@work = current_user.works.create(params[:work])
redirect_to current_user
end
def edit
@work = current_user.works.find(params[:id])
end
def new
@work = current_user.works.new
end
def destroy
@work = current_user.works.find(params[:id]).destroy
flash[:success] = "Work deleted"
redirect_to current_user
end
def update
@work = current_user.works.find(params[:id])
if @work.update_attributes(params[:work])
flash[:success] = "Profile updated"
redirect_to @work
else
render 'edit'
end
end
def show
@work = Work.find(params[:id])
@comment = @work.comments.build
@comment.user = current_user
@activities = PublicActivity::Activity.order("created_at DESC").where(trackable_type: "Work", trackable_id: @work).all
@comments = @work.comments.order("created_at DESC").where(work_id: @work ).all
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @work }
end
end
end
And lastly, here is the Comments controller:
class CommentsController < ApplicationController
before_filter :authenticate_user!
def index
@comments = Comment.all
end
def show
@comment = Comment.find(params[:id])
@activities = PublicActivity::Activity.order("created_at DESC").where(trackable_type: "Comment", trackable_id: @comment).all
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @comment }
end
def update
@comment = current_user.comments.find(params[:id])
if @comment.update_attributes(params[:comment])
flash[:success] = "Comment updated"
redirect_to @comment
end
end
def create
@work = Work.find(params[:id])
@comment = @work.comments.build(params[:comment])
@comment.user = current_user
if @comment.save
#flash[:success] = "Post created!"
redirect_to @work
else
render 'home#index'
end
end
end
end
When I attempt to submit a comment using the comment form on the works show view page, I get the following error:
Activerecord::RecordNotFound in CommentsController#create
Couldn't find Work without an ID
Why can't the application find the Work so that it can associate the comment to it?
EDIT 1: Thanks to the answers below I edited the comment form:
<%= form_for(@work, @comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :content, placeholder: "Post feedback or contribute content
to this work!" %>
</div>
<%= f.submit "Post", class: "btn btn-small btn-primary" %>
<% end %>
I'm still getting the same error after making the change to the form and adding the nested route.
I edited the routes file to include a nest for work comments:
authenticated :user do
root :to => 'activities#index'
end
root :to => "home#index"
devise_for :users
resources :users do
member do
get :following, :followers, :posts, :comments
end
end
resources :works do
resources :comments
end
resources :relationships, only: [:create, :destroy]
resources :posts
resources :activities
resources :comments
Rake routes shows the following for Comments#create: POST /comments(.:format)
The POST URL (where the error shows up) is appURL/works/1/comments
Doesn't seem right. What do I need to change? Thank you so much for the help so far!!
Upvotes: 1
Views: 10071
Reputation: 25049
Your form needs to be form_for([@work, @comment])
so that Rails knows to build a URL like /works/123/comments
. Right now it would just be posting to /comments
.
Check your rake routes
to see the route for your CommentsController#create action. You might also need to tweak the controller to read params[:work_id]
instead of params[:id]
.
Upvotes: 3
Reputation: 11504
The view helper form_for(@comment)
will post to '/comments' by default. You can specify a url (see the guides) that includes the :id
of the work record. The typical approach is to use form_for([@work, @comment])
and Rails will do this for you so long as you've set up your routes with comments as a nested resource of work.
Upvotes: 1