質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.99%

  • Ruby

    6388questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

コメントがトップページに表示されません

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 97

begin1990

score 21

やりたいこと
トップページにコメント一覧を表示させる

問題点
https://gyazo.com/e07751929a071e6d52390b314ae87ae0の画面で、コメント投稿をしたところ、コメントがトップページに表示されません(コンソール上ではコメントが保存されいています)。

現在のコードは以下の通りです。
toppages.controller.rb

class ToppagesController < ApplicationController
  def index
    if logged_in?
      @user = current_user
      @post = current_user.posts.build  # form_for 用
      @posts = current_user.feed_posts.order('created_at DESC').page(params[:page])
      @post_comment = current_user.post_comments.build
      @post_comments = @post.post_comments.order('created_at DESC').page(params[:page])
    end
  end
end

posts_controller.rb

class PostsController < ApplicationController
  before_action :require_user_logged_in
  before_action :correct_user, only: [:destroy]

  def index
    @post_comment = current_user.post_comments.build
  end

  def show
    @post = Post.includes(:user).find(params[:id])
  end

  def create
    @post = current_user.posts.build(post_params)
    if @post.save
      flash[:success] = 'メッセージを投稿しました。'
      redirect_to root_url
    else
      @posts = current_user.feed_posts.order('created_at DESC').page(params[:page])
      flash.now[:danger] = 'メッセージの投稿に失敗しました。'
      render 'toppages/index'
    end
  end

  def destroy
    @post.destroy
    flash[:success] = 'メッセージを削除しました。'
    redirect_back(fallback_location: root_path)
  end

  private

  def post_params
    params.require(:post).permit(:picture, :content)
  end

  def correct_user
    @post = current_user.posts.find_by(id: params[:id])
    unless @post
      redirect_to root_url
    end
  end
end

post_comments.controller.rb

class PostCommentsController < ApplicationController
  before_action :require_user_logged_in
  before_action :correct_user, only: [:destroy]

  def create
    @post = Post.find(params[:post_id])
    @post_comment = @post.post_comments.create(post_comment_params)
    @post_comment.user_id = current_user.id
    #@post_comment = current_user.post_comments.build(post_comment_params)
    #@comment = Comment.create(text: comment_params[:text], post_id: comment_params[:post_id], user_id: current_user.id)
    if @post_comment.save
      flash[:success] = "コメントしました。"
      #redirect_to "/posts/#{@comment.post.id}"
      #redirect_to post_comments_path(@post.id)
      #redirect_to :action =>"new"
      redirect_to root_url
    else
      @post_comments = @post.post_comments.order('created_at DESC').page(params[:page])
      flash.now[:danger] = 'コメントの投稿に失敗しました。'
      render 'toppages/index'
    end
  end

  def destroy
    @post_comment.destroy
    flash[:success] = 'コメントを削除しました。'
    redirect_back(fallback_location: root_path)
  end

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

    # Never trust parameters from the scary internet, only allow the white list through.
  def post_comment_params
    params.require(:post_comment).permit(:user_id, :post_id, :content)
  end

  def correct_user
    @post_comment = current_user.post_comments.find_by(id: params[:id])
    unless @post_comment
      redirect_to root_path
    end
  end
end

comments/_comments.html.erb

<ul class="media-list">
  <% @post_comments.each do |post_comment| %>
  <% user = post_comment.user %>
    <div>
      <p>投稿者:<%= link_to user.name, user_path(user) %> <span class="text-muted">commented at <%= post_comment.created_at %></span></p>
    </div>
    <p><%= post_comment.content %></p>
    <div>
      <% if current_user == post_comment.user %>
        <%= link_to "削除", post_comment, method: :delete, data: { confirm: "本当に削除してよろしいですか?" }, class: 'btn btn-danger btn-sm' %>
      <% end %>
    </div>
  <% end %>
  <%= paginate @post_comments %>
</ul>

posts/_posts.html.erb

<ul class="media-list">
  <% posts.each do |post| %>
    <% user = post.user %>
    <li class="media">
      <div class="media-left">
        <img class="media-object img-rounded" src="<%= gravatar_url(user, options = { size: 50 }) %>" alt="">
      </div>
      <div class="media-body">
        <div>
          <%= link_to user.name, user_path(user) %> <span class="text-muted">posted at <%= post.created_at %></span>
        </div>
        <div>
          <p><%= image_tag post.picture,:size =>"280x210" %></p>
          <p><%= post.content %></p>
          <%= render 'comments/comments', post_comments: @post_comments %>
          <br/>
          <% if current_user %>
            <%= form_for [post, Comment.new] do |form| %>
              <%= form.text_area :content, cols: "30", placeholder: "コメントする", rows: "2" %>
              <%= form.submit "コメントの投稿" %>
            <% end %>
          <% end %>  
        </div>
        <div>
          <% if current_user == post.user %>
            <%= link_to "削除", post, method: :delete, data: { confirm: "本当に削除してよろしいですか?" }, class: 'btn btn-danger btn-sm' %>
          <% end %>
        </div>
      </div>
    </li>
  <% end %>
  <%= paginate posts %>
</ul>

toppages/index.html.erb

  <% if logged_in? %>
    <div class="row">
      <aside class="col-md-4">
        <%= form_for(@post, html: {multipart: true}) do |f| %>
          <div class="form-group">
            <%= f.label :picture, '写真' %>
            <%= f.file_field :picture %><br />
            <%= f.label :content, 'コンテンツ' %>
            <%= f.text_area :content, class: 'form-control', rows: 5 %>
          </div>
          <%= f.submit '投稿', class: 'btn btn-primary btn-md' %>
        <% end %>
      </aside>
      <div class="col-xs-8">
        <%= render 'posts/posts', posts: @posts %>
      </div>
    </div>
  <% else %>
    <div class="cover">
      <div class="cover-inner">
        <div class="cover-contents">
          <h1>毎日のつながりは、ここから始まる</h1>>
          <%= link_to 'まずは会員登録から', signup_path, class: 'btn btn-success btn-md' %>
          <%= link_to '会員の方はこちら', login_path, class: 'btn btn-success btn-md' %>
        </div>
      </div>
    </div>
  <% end %>

toppages_controller.rbに

@post_comment = current_user.post_comments.build
      @post_comments = @post.post_comments.order('created_at DESC').page(params[:page])


を入れれば表示されると思っていましたが、全く表示されませんでした。

他にも色々試しましたが、それでもコメントは表示されませんでした。
これ以上、トップページに投稿したコメントを表示させる方法がわからないので、どなたかご教示をお願いできませんか?

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • scivola

    2018/02/04 15:53

    各ビューのところに,そのテンプレートファイルのパスを追記してもらえますか。

    キャンセル

  • begin1990

    2018/02/04 16:15

    各ビューのところに,そのテンプレートファイルのパスを追記したつもりですが、「○○.html.erb」という形でよろしいでしょうか?

    キャンセル

  • scivola

    2018/02/04 16:35

    ファイル名だけじゃなくてファイルパスを書いてほしいんです。app/views は略してもいいですが,そのあとのディレクトリー名は略さないで。なぜかというと,そのファイルがどこに置かれているか,ということがとても重要なので。

    キャンセル

  • begin1990

    2018/02/04 16:40

    ファイルパスも追記しました。

    キャンセル

回答 1

checkベストアンサー

0

posts/posts ビューの

render 'comments/comments', comments: @comments

render 'comments/comments', comments: post.comments

に変えたらどうなりますか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/02/04 13:38 編集

    それでも変わりませんでした。
    というのは、toppages_controller内の@postは、入力用にbuildされた新しいモデルのインスタンスなので、当然@post.commentsは空っぽになるからです。

    キャンセル

  • 2018/02/04 13:52

    @post じゃなくて post ですよ?

    キャンセル

  • 2018/02/04 14:04

    トップページコントローラの8行目を、
    @post_comments = post.post_comments.order('created_at DESC').page(params[:page])
    に変える、ということでしょうか?

    キャンセル

  • 2018/02/04 15:51

    いえ,そうではありません。
    私が提示したコードでは `@post` を使っていないのに `@post` の話をされているので,何か誤解があるのでは,と。

    キャンセル

  • 2018/02/04 16:19

    ごめんなさい。もしかするとtoppages_controllerの@postが関係しているのかなと思いまして、その話をしてしまいました。
    <%= render 'comments/comments', post_comments: post.post_comments %>にしても変わりありませんでした。
    また、commentsは、postと区別しやすくしたいため、全体的に「post_comments」に変えてあります(modelはpost_comment、テーブルはpost_comments、等)。

    キャンセル

  • 2018/02/04 16:57 編集

    質問投稿時からコードを書き換えられると話がこんがらがるので,変えないでください。

    現状のコードに即していうと,
    toppages/index.html.erb で
    render 'posts/posts', posts: @posts
    とやって,posts/_posts.html.erb を呼び出しているんですよね?
    で,そのとき,posts っていうローカル変数を渡してますよね?

    で,posts.html.erb において
    posts.each do |post|
    # 云々
    end
    というループを回してますよね。
    ループの中では,post というブロックパラメーターに個々の Post オブジェクトが入っているわけですよね。
    で,そのループの中で,post.content を表示してますよね。
    その直後に,その post のコメント一覧を表示したいわけですよね。

    そのコメント一覧は comments/_comments.html.erb で表示するんですよね。
    そのため render を使うわけですが,
    render 'comments/comments', post_comments: @post_comments
    となっているのがおかしいです。

    なぜここでいきなり @post_comments が出てくるのですか。
    post のコメントたちは post.comments で得られるはずです。それを渡してやらなければなりません。
    つまり,正しくは
    render 'comments/comments', post_comments: post.comments
    です。
    さっきから書いているのはそのことです。

    で,comments/_comments.html.erb の中身もおかしいです。
    せっかくローカル変数 post_comments が渡されているのに,それを使わず
    @post_comments.each do |post_comment|
    # 云々
    end
    と,インスタンス変数 @post_comments を使っています。これを post_comments に変えましょう。

    これで直りませんか?

    キャンセル

  • 2018/02/04 17:06

    ありがとうございます。
    おかげで解決できました!

    キャンセル

  • 2018/02/04 17:21

    ああよかった。
    現状では,不要なインスタンス変数定義(代入)がいろいろ残っているので,要らないのは消しておきましょうね。

    コントローラーのアクションとテンプレートおよび部分テンプレートの間の値の受け渡し方法について。
    コントローラーからはインスタンス変数で渡します。コントローラーで代入さえしておけば,ほかには何もしなくても,テンプレートおよびその先の部分テンプレートで参照できます。
    一方,テンプレートから部分テンプレートへはすでに見たような方法で,ローカル変数として渡します。render メソッドのオプションのハッシュのキーの名前が,部分テンプレート側で参照できるローカル変数の名前になります。
    というようなことが理解できていれば,今後は惑わずに済むのではないでしょうか。

    キャンセル

  • 2018/02/04 17:50

    つまり、先ほどの例で言うと、「posts/_posts.html.erb」から、「post_comments/_post_comments.html.erb」へ値を渡す際は、ローカル変数として渡す、という考えでよろしいでしょうか?

    キャンセル

  • 2018/02/04 18:12

    そうです。

    キャンセル

  • 2018/02/04 18:27

    ご説明ありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    6388questions

    Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。