简体   繁体   中英

Micropost's comments on users page (Ruby on Rails)

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:

resources :microposts do
  resources :comments
end

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:

def create
  @micropost = Micropost.find(params[:micropost_id])
  @comment = Comment.new(params[:comment])
  @comment.micropost = @micropost
  @comment.user = current_user

  if @comment.save
    ...
end

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

<%= render 'shared/comment_form', micropost: micropost %>

Then add the micropost to the comment form_for call

<%= form_for([micropost, @comment]) do |f| %>

Make sure your routes are nested

# in routes.rb
resources :microposts do
  resources :comments
end

Then build the comment off of the micropost in the CommentsController

def create
  @micropost = Micropost.find(params[:micropost_id])
  @comment = @micropost.comments.build(params[:comment])
  ...
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM