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

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

ただいまの
回答率

91.01%

  • Ruby on Rails

    6191questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

ParameterMissingを解決できません

受付中

回答 1

投稿 編集

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

begin1990

score 21

現在、「param is missing or the value is empty: comment」というエラーが、CommentsController#createで発生しています。
http://original-app-takasakifuse.c9users.io:8080/posts/5/comments

コードは以下の通りです。
toppage_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])
      @comment = @post.comments.build
      @comments = @post.comments.order('created_at DESC').page(params[:page])
    end
  end
end

comment_controller

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.create(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
      @comments = @comments.order('created_at DESC').page(params[:page])
      flash.now[:danger] = 'コメントの投稿に失敗しました。

      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


user_controller

class UsersController < ApplicationController
  before_action :require_user_logged_in, only: [:index, :show, :edit, :destroy, :followings, :followers]

  def index
    @users = User.all.page(params[:page])
  end

  def show
    @user = User.find(params[:id])
    @posts = @user.posts.order('created_at DESC').page(params[:page])
    @comment = Comment.create(user_id: @user.id)
    @comments = @posts.comments
    counts(@user)
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      flash[:success] = 'ユーザを登録しました。'
      redirect_to @user
    else
      flash.now[:danger] = 'ユーザの登録に失敗しました。'
      render :new
    end
  end

  def edit
    @user = User.find(params[:id])
    render :edit
  end

  def update
    @user = User.find(params[:id])

    if @user.update_attributes(user_params)
      redirect_to @user
      flash[:success] = "プロフィールを更新しました" 
    else
      flash.now[:danger] = 'プロフィールを更新できませんでした。'
      render'edit'
    end
  end

  def destroy
    @user = User.find(params[:id])
    @user.destroy
    flash[:success] = 'ユーザー登録を解除しました。'
    redirect_back(fallback_location: root_url)
  end

  def followings
    @user = User.find(params[:id])
    @followings = @user.followings.page(params[:page])
    counts(@user)
  end

  def followers
    @user = User.find(params[:id])
    @followers = @user.followers.page(params[:page])
    counts(@user)
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation, :introduction, :address, :age)
  end
end


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>
            <% if @comments %>
              <% @comments.each do |comment| %>
                <div class="name2">投稿者:<%= link_to comment.user.username, "/users/#{comment.user_id}" %>&nbsp;&nbsp;投稿日時:<%= comment.created_at.strftime("%Y-%m-%d %H:%M:%S") %></div>
                <div class="name2"><%= comment.text %></div>
              <% end %>
            <% end %>
          <br/>
          <% 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 %>
        </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>

コメントのマイグレーションファイル

class CreateComments < ActiveRecord::Migration[5.0]
  def change
    create_table :comments do |t|
      t.references :user, foreign_key: true
      t.references :post, foreign_key: true
      t.string :content

      t.timestamps
    end
  end
end

コメントのモデル

class Comment < ApplicationRecord
  belongs_to :user
  belongs_to :post
end


ルーティング
routes.rb

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

/posts を表示したときのコメントのフォームの <form> タグの部分(ブラウザーで HTML ソースを表示してその HTML 断片)

<form class="new_comment" id="new_comment" action="/posts/5/comments" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="&#x2713;" /><input type="hidden" name="authenticity_token" value="4i0OQgfiY2xoD/pIvEJI9XtKhTfJnyjRfZAVOVJ9i9wvQSHu/zWiXB7b6HA35FG0AdkwxgS4AgM2jPEkA+r+Ug==" />
              <textarea cols="30" placeholder="コメントする" rows="2" name="comment[content]" id="comment_content">
</textarea>
              <input type="submit" name="commit" value="コメントの投稿" data-disable-with="コメントの投稿" />
</form>

やりたいこと:トップページに表示されているPostにコメントを投稿する。

やったこと:http://nograve.hatenadiary.jp/entry/2015/11/05/161948を参考に、user_controllerのusers#showの部分を修正した。

このようにしても解決できませんでした。

なぜ、ParameterMissingが発生しているのか?
これを解決するにはどうすればいいのか?

以上についてご教示していただけないでしょうか?

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

0

コメントのフォームの書き方が間違っています。

こういうときは,ログファイルを見て,どのようなリクエストが来て,Parameters がどんなかを見ます。
ログファイルじゃなくても,rails server したターミナル上で刻々とリクエストなどの情報が見えますよね。そこを見れば分かります。

フォームは

<%= 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 %>

となっていますよね。
まず,Comment モデルのコメント本文は content のはずなのに textarea の name が text になっているのがおかしいですが,エラーが出たのはそれ以前の問題です。

CommentsConroller の create アクションでは,Comment オブジェクトを作るために,コントローラーの private メソッドである comment_params を使いますよね。その定義は

def comment_params
  params.require(:comment).permit(:user_id, :post_id, :content)
end

となっています。この require は,リクエストのパラメーター(ログに Parameters として見えているデータ)から comment をキーとする部分を取り出そうとするのですが,Parameters はきっと

Parameters: {"utf8"=>"✓", "authenticity_token"=>"云々", "text"=>"あいうえお"}

みたいになっているはずです。comment が見当たりませんね。これがエラーの原因です。

正しいフォームは,例えば以下のように書きます。

<%= form_for [post, Comment.new] do |form| %>
  <%= form.text_area :content, cols: "30", placeholder: "コメントする", rows: "2" %>
  <%= form.submit "コメントの投稿" %>
<% end %>

いや,Rails 5.1 以降なら form_with を使うほうがいいのでしょうが,私が慣れていないためとりあえず form_for を使う書き方にしてみました。

ま,ともかく正しいフォームの場合,リクエストのパラメーターは

Parameters: {"utf8"=>"✓", "authenticity_token"=>"云々",
  "comment"=>{"content"=>"あいうえお"},
  "commit"=>"コメントの投稿",
  "post_id"=>"1"}

みたいになったはずです。(長いので改行を入れました)

comment_params の require(:comment) はこの中の "comment" をキーとする部分を持ってくるってことです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/22 23:49 編集

    ご回答ありがとうございます。
    フォームの所を、おっしゃる通り
    <%= form_for [@post, Comment.new] do |form| %>
    <%= form.text_area :content, cols: "30", placeholder: "コメントする", rows: "2" %>
    <%= form.submit "コメントの投稿" %>
    <% end %>
    に変更したところ、再び「No route matches {:action=>"create", :controller=>"comments", :post_id=>nil} missing required keys: [:post_id]」が発生してしまいました。

    エラー内容
    https://gyazo.com/55934603a5abe2787d69b490a13d6e51

    この場合、トップページコントローラのindexアクションに何か追加する必要はありますか?

    キャンセル

  • 2018/01/23 00:14

    ごめんなさい,今の場合,コメントすべき Post は @post じゃなくて post に入っているんですね。なので,form_for に渡す配列の第一要素は @post でなく post としてください。(回答は修正しました)
    それから,エラー画面を見ると,私が書いた Comment.new を Comment.create に修正されているのと,ブロックパラメーターも form から f に修正されていますね。これがまずおかしいです。
    それから routes.rb を見せてください。

    キャンセル

  • 2018/01/23 00:28

    申し訳ありません。せっかくご回答くださったのに、私の方で修正してしまって。

    それと、ルーティングも追加しました。

    キャンセル

  • 2018/01/23 12:27

    うーん,手元で同じようなのを作ってコメントが付けられることを確認しているんですが,どこかに見落としがあったかなあ。
    では,/posts を表示したときのコメントのフォームの <form> タグの部分(ブラウザーで HTML ソースを表示してその HTML 断片)を見せてもらえますか。

    キャンセル

  • 2018/01/23 19:48

    フォームの <form> タグの部分を追加しました。

    キャンセル

  • 2018/01/26 08:21

    もう一度,現在のエラーの情報を詳しく教えてもらえますか。
    何をどうしたときにどこで(コードのどの部分で)どういうエラーが出たのかを。

    キャンセル

  • 2018/01/26 12:53

    只今仕事中ですので、返事は今夜になります。
    よろしくお願いします。

    キャンセル

  • 2018/01/26 21:32 編集

    お待たせ致しました。
    現在は、トップページにコメントを表示させるため、toppages#indexに、
    @comment = @post.comments.build
    @comments = @post.comments.order('created_at DESC').page(params[:page])
    を追加したところ、投稿したコメントが表示されていません。

    キャンセル

  • 2018/01/26 22:08

    えっ? ParameterMissing の話はどうなったのですか。そっちは解決したのでしょうか?

    キャンセル

  • 2018/01/26 22:10

    そちらの方は大丈夫です。

    キャンセル

  • 2018/01/26 22:52

    別の問題に移ったのでしたら,質問を新しく立てていただけますか。

    キャンセル

  • 2018/01/26 23:34

    わかりました。

    キャンセル

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

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

関連した質問

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

  • Ruby on Rails

    6191questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。