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

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

ただいまの
回答率

90.12%

UrlGenerationErrorを解決できません。

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 2,124

begin1990

score 29

現在、UrlGenerationError in Toppages#indexが発生しています。

詳しく書くと、「No route matches {:action=>"create", :controller=>"comments", :post_id=>nil} missing required keys: [:post_id]」です。

恐らく、postのidが渡っていないためエラーが起きていると考えられます。

現在のコードは以下の通りです。

ビュー部分

<% if current_user %>
            <%= form_tag(post_comments_path(@post.id), method: :post) do %>
            <textarea cols="30" name="text" placeholder="コメントする" rows="2"></textarea>
            <br/>
            <input type="submit" value="コメントの投稿">
            <% end %>
          <% end %>

コメントコントローラー

class CommentsController < ApplicationController
  before_action :set_comment, only: [:new,:create, :destroy]
  before_action :require_user_logged_in

  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.new(comment_params)
    @comment.user_id = current_user.id
    #@comment = current_user.posts.comments.build(comment_params)
    #@comment = Comment.create(text: comment_params[:text], post_id: comment_params[:post_id], user_id: current_user.id)
    if @comment.save
      flash[:success] = "コメントしました。"
      #redirect_to "/posts/#{@comment.post.id}"
      #redirect_to post_comments_path(@post.id)
      #redirect_to :action =>"new"
      redirect_back(fallback_location: root_path)
    else
      render 'toppages/index'
    end
  end

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

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

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

ルーティング

Rails.application.routes.draw do
  root to: 'toppages#index'

  get 'login', to: 'sessions#new'
  post 'login', to: 'sessions#create'
  delete 'logout', to: 'sessions#destroy'

  resources :users do
    member do
      get :followings
      get :followers
    end
    collection do
      get :search
    end
  end

  resources :posts, only: [:create, :destroy, :show]  , shallow: true do
    resources :comments, only: [:create, :destroy]
  end

  resources :relationships, only: [:create, :destroy]
  get 'signup', to: 'users#new'
end

トップページのcontroller

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])
    end
  end
end

ビュー部分を、<%= link_to "コメントを投稿", method: :post, :action =>"create", :controller =>"comments", :post_id =>nil, class: 'btn btn-danger btn-sm' %>や、<%= form_tag(post_comments_path(@post.id), :action =>"create", :controller =>"comments", :post_id =>nil, method: :post) do %>としてみたり、コントローラーのコメントアウト部分を一時有効にしてみたり、ググったりしてみましたが、中々解決できませんでした。

どなたかわかる方、ご教示お願い申し上げます。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • begin1990

    2018/01/19 20:17 編集

    scivolaさん、大変お待たせ致しました。現在は、```<%= form_tag(post_comments_path(@post.id), method: :post) do %>```の行で、https://gyazo.com/cee7eaba2c670e2845d38f3a91ad15fa というエラーが発生しています。
    ちなみに、これはトップページにアクセスしたときに発生しています。

    キャンセル

  • scivola

    2018/01/20 13:37

    ToppagesController の index アクションでエラーが起こっているので,そのアクションの定義を見せてください

    キャンセル

  • begin1990

    2018/01/20 13:40

    トップページのcontrollerを追加しました。

    キャンセル

回答 1

0

ToppagesController の index において,

@post = current_user.posts.build

としてますよね。
これで @post には Post オブジェクトが入るわけですが,この Post オブジェクトはデータベースにはまだ記録されていません。したがって,id カラムの値は nil です。

しかるに,ビューにおいて

post_comments_path(@post.id)

で URL を作ろうとしています。
@post.id は nil ですから,URL が作れません。
それが

No route matches {:action=>"create", :controller=>"comments", :post_id=>nil}

というエラーの意味するところです。

このフォームは何のためにあるかというと,投稿(Post)に対してコメントを付ける(Comment を作る)ためですよね。
であれば特定の(すでにデータベースに入っている)Post を持ってこなければなりません。
だからコントローラーで

@post = current_user.posts.build

として Post オブジェクトを作成するのはおかしいんです。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/21 18:04

    ご回答ありがとうございます。
    おっしゃる通り、ビューの中で @posts.each do |post| みたいなループがあり、そのループのなかにコメント用のフォームがあれば良いのです。
    form_tag(post_comments_path(post.id), method: :post)に修正した所、UrlGenerationError in Toppages#indexは無くなりましたが、今度は別のエラーが発生しました。
    https://gyazo.com/7aee6998437a99d0075840677d544aca
    コメントコントローラも、一部ではなく全て貼り付けました。
    これ以上長くなりそうなので、別件で質問した方が良いでしょうか?

    キャンセル

  • 2018/01/22 06:12

    set_comment というのは既存の Comment オブジェクトを @comment にだいにゅうするためのものですよね。
    でも
    before_action :set_comment, only: [:new,:create, :destroy]
    となっっています。
    new や create する段階ではまだデータベースに入ってないので,set_comment するのはおかしいですね。

    キャンセル

  • 2018/01/22 12:55

    ご回答ありがとうございました。
    before〜という部分は削除した方がいいですね。

    キャンセル

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

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

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