On user's page i have many microposts and i want to add comment form and comments to each micropost.
I have three models: User, Micropost, Comment.
user.rb
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
has_many :comments
end
micropost.rb
class Micropost < ActiveRecord::Base
belongs_to :user
has_many :comments, dependent: :destroy
end
comment.rb
class Comment < ActiveRecord::Base
attr_accessible :comment_content
belongs_to :user
belongs_to :micropost
validates :comment_content, presence: true
validates :user_id, presence: true
validates :micropost_id, presence: true
end
comments_controller.rb
class CommentsController < ApplicationController
def create
@comment = current_user.comments.build(params[:comment])
if @comment.save
flash[:success] = "Comment created!"
redirect_to current_user
else
render 'shared/_comment_form'
end
end
end
_micropost.html.erb
<tr>
<td class="micropost">
<span class="content"><%= wrap(micropost.content) %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<%= render 'shared/comment_form' %>
</td>
</tr>
Comment form
<%= form_for(@comment) do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="field">
<%= f.text_area :comment_content %>
</div>
<button class="btn" type="submit">
Create
</button>
<% end %>
Every micropost must have its own comments. In my DB i have comment table with
id / comment_content / user_id / micropost_id
columns.
Comment is not creating because RoR can't understand to which micropost belongs this new comment. What should i do to have all needed information in my DB?
UPDATE
users_controller
def show
@user = User.find(params[:id])
@microposts = @user.microposts.paginate(page: params[:page])
@comment = Comment.new
end
microposts_controller
def create
@micropost = current_user.microposts.build(params[:micropost])
if @micropost.save
flash[:success] = "Micropost created!"
redirect_to current_user
else
render 'shared/_micropost_form'
end
end
SOLUTION!!!
Big thanks to carlosramireziii and Jon! They are both right
comments_controller
def create
@micropost = Micropost.find(params[:micropost_id])
@comment = Comment.new(params[:comment])
@comment.micropost = @micropost
@comment.user = current_user
if @comment.save
flash[:success] = "Comment created!"
redirect_to current_user
else
render 'shared/_comment_form'
end
end
_micropost.html.erb
<%= render 'shared/comment_form', micropost: micropost %>
Comment form
<%= form_for([micropost, @comment]) do |f| %>
routes.rb
resources :microposts do
resources :comments
end
I would use nested resources for micropost and comments like this in your routes.rb file:
Then in your comments controller, which you access through the
micropost_comments_path(@micropost)
url helper you can do the following to build the association in the create action:You could reduce the number of lines of code using the merge method, but I find that this sometimes reduces the readability of your code, and since you'll need the @micropost object if redisplaying the form after validation errors you may as well just fetch the record.
Try passing in the current micropost to the comment partial
Then add the micropost to the comment
form_for
callMake sure your routes are nested
Then build the comment off of the micropost in the
CommentsController