How do I make sure each post in the Post feed show

2019-08-17 06:39发布

I have a Post model, and a Comment model that belongs to Post. I was able to display the Post in the home view corresponding to the home controller and home action and the User/show view. Thus, in the home and user views, the posts are listed in order of creation time. I was also able to have a post form in both the user and home views and a comment form in the home and user views.

The problem arises when I try to display the comment underneath each displayed Post in the home and user views. How can I list the comments associate with each post under the post in the home and user views ?

How do I make sure the comments in the databased are listed under the corresponding post ?

Here is my comments controller:

class CommentsController < ApplicationController
 def index
 @comments =Comment.all.paginate(page: params[:page])
  end
 def show
 @comment = Comment.find(params[:id])
 @post = @Comment.post
 end
 def new
 end
 def create
 @comment = Comment.new(comment_params)
  if @comment.save
  flash[:success] = "Comment created"
  redirect_to :back
  else
  render 'new'
  end
  end
  def edit
  @comment = Comment.find(params[:id])
  end
  def update
  @comment = comment.find(params[:id])
  if @comment.update_attributes(comment_params)
  flash[:success] = "Comment updated"
  redirect_to @comment.post
  else
  render 'edit'
  end
  end
  def destroy
    Comment.find(params[:id]).destroy
    flash[:success] = "Comment deleted"
    redirect_to users_url
  end  
  private
  def comment_params
  params.require(:comment).permit(:author_name, :body)
  end
  end

Here is my home view: app/views/home/home.html.erb:

<% if logged_in? %>
  <div class="row">
    <aside class="col-md-4">
    <section class="user_info">
      <%= render 'shared/user_info' %>
    </section>
    <hr/>
    <br/>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
    <section class="post_form">
      <%= render 'shared/post_form' %>
      </section>
    </aside>
    <div class="col-md-8">
      <h3>Post Feed</h3>
      <%= render 'shared/feed' %>
    </div>
  </div>
<% else %>
  <div class="center jumbotron">
    <h1>Welcome to the Unstarv website</h1>
    <h2>
      Please sign up now to use this site
      <%= link_to "Sign Up",  signup_path =%> 
      now.
    </h2>
    <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
  </div>
  <%= link_to image_tag("rails.png", alt: "unstarv logo"), '#' %>
<% end %>

And here is my home controller:

class HomeController < ApplicationController
  def home
    if logged_in?
      @post  = current_user.posts.build
      @feed_items = current_user.feed.paginate(page: params[:page])  
    end
  end

  def about
  end

  def privacy
  end

  def terms
  end
end

And here is my Post model, the relevant part:

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :comments
  default_scope -> { order(created_at: :desc) }
  mount_uploader :picture, PictureUploader
end

The relevant part of my User model:

class User < ActiveRecord::Base
  attr_accessor :remember_token
  before_save { self.email = email.downcase }
  has_many :posts, dependent: :destroy
  has_many :comments
  has_many :active_relationships, class_name:  "Relationship",
    foreign_key: "follower_id",
    dependent:   :destroy
  has_many :passive_relationships, class_name:  "Relationship",
    foreign_key: "followed_id",
    dependent:   :destroy
  has_many :following, through: :active_relationships, source: :followed  
  has_many :followers, through: :passive_relationships, source: :follower
  validates :username,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, length: { minimum: 6 }, allow_blank: true

  def feed
    following_ids = "SELECT followed_id FROM relationships WHERE  follower_id = :user_id"
    Post.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id)
  end
end

And here is my Comment model:

class Comment < ActiveRecord::Base
  belongs_to :post
  belongs_to :user
  default_scope -> { order(created_at: :desc) }  
end

And here is the post controller:

class PostsController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]
  def index
    @posts = Post.all
  end
  def show
    @post = Post.find(params[:id])
    @comment = Comment.new
    @comment.post_id = @post.id
    @comments = @post.comments.all
  end
  def new
    @post = Post.new
  end
  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      flash[:success] = "Post created!"
      redirect_to root_url
    else
      @feed_items = []
      render 'home/home'
    end
  end
  def edit
    @post = Post.find(params[:id])
  end
  def update
    @post = Post.find(params[:id])
    @post.update(post_params)
    flash.notice = "Post '#{@post.title}' Updated!"
    render 'home/home  '
  end

  def update
    @post = Post.find(params[:id])
    @post.update(post_params)
    flash.notice = "Post '#{@post.title}' Updated!"
    redirect_to root_url
  end

  private
  # Use callbacks to share common setup or constraints between actions.
  def set_post
    @post = Post.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def post_params
    params.require(:post).permit(:title, :body, :picture)
  end
end

Here is my app/views/post/_post.html.erb file,

<li id="post-<%= post.id %>">
  <span class="user"><%= link_to post.user.username, post.user %></span>
  <span class="content">
    <%= post.title %>
    <%= post.body %>
    <%= image_tag post.picture.url if post.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(post.created_at) %> ago.
    <% if current_user?(post.user) %>
    <%= link_to "delete", post, method: :delete,
        data: { confirm: "You sure?" } %>
        <% end %>
  </span>
  <section>
    <h2>Your Comments here</h2>
    <h3>Post a Comment</h3>
    <h3>Post a Comment</h3>
    <%= render 'shared/comment_form' %>
    <% post.comments.all.each do |comment| %>
    <h4><small>Comment by</small> <%= comment.post.user.username %></h4> 
    <p class="comment"><%= comment.body %></p>
    <p><small>Posted <%= distance_of_time_in_words(Time.now,     comment.created_at) %> ago</small></p>
    <br/>
    <%end%>
</li>

And here is my app/views/shared/comment_form_html.erb , which works fine:

<%= form_for [ post, post.comments.build] do |f| %>
  <p>
    <%= f.label :body, "Your Comment" %><br/>
    <%= f.text_area :body %>
  </p>
  <p>
    <%= f.submit 'Submit' .  method="post", class: 'btn btn-primary' %>
  </p>
<% end %>

Here is my app/views/posts/_post.html.erb

<li id="post-<%= post.id %>">
<span class="user"><%= link_to post.user.username, post.user %></span>
<span class="content">
<%= post.title %>
<%= post.body %>
<%= image_tag post.picture.url if post.picture? %>
</span>
<span class="timestamp">
Posted <%= time_ago_in_words(post.created_at) %> ago.
<% if current_user?(post.user) %>
 <%= link_to "delete", post, method: :delete,
                                   data: { confirm: "You sure?" } %>
<% end %>
</span>
<h2>Comments</h2>
<h3>Post a Comment</h3>
<%= render 'shared/comment_form', post: post %>       
<h3>Comments (<%= post.comments.size %>)</h3>
<% post.comments.each do |comment| %>
<h4><small>Comment by</small> <%= comment.post.user.username %></h4>
<p class="comment"><%= comment.body %></p>
<p>Posted <%= distance_of_time_in_words(Time.now, comment.created_at) %> ago</p>
</li>
<br/>
<%end%>

Thanks a lot for your help !!!!

1条回答
再贱就再见
2楼-- · 2019-08-17 07:23

The issue is related in how you are creating the comments.

With the actual code, the comment does not belong to any post so in your comments_controller change create action to something like:

def create
  post = Post.find(params[:post_id])
  @comment = post.comments.build(comment_params)
  if @comment.save
    flash[:success] = "Comment created"
    redirect_to :back
  else
    render 'new'
  end
end
查看更多
登录 后发表回答