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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby on Rails

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

Q&A

解決済

1回答

1816閲覧

【Ruby on Rails】コメント機能実装

keigo555

総合スコア1

Ruby on Rails

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

0グッド

0クリップ

投稿2021/05/23 14:32

前提・実現したいこと

Ruby on Railsのコメント機能実装で躓いています。

目標は、Yahoo!ニュースnewspicksのような
ニュース投稿機能(postモデル)に紐づくコメント(commentモデル)投稿機能の実装です。

発生している問題・エラーメッセージ

以下の画像のようにNilClassのNoMethodErrorが発生しています。

postsコントローラのshowページにコメント用のform_withを設置しています。
そこからcommentsコントローラのcreateアクションにデータを渡し
テーブルに保存する工程でpostのidが上手く処理されていないようです。

イメージ説明

該当のソースコード

※schemaやコントローラは長いので、関係ありそうなところを抜粋しています。

■ルーティング

routes

1 resources :posts do 2 resources :comments, :only => [:create, :destroy, :edit, :update] 3 end

■テーブル、モデル

schema

1 create_table "comments", force: :cascade do |t| 2 t.integer "user_id", null: false 3 t.integer "post_id", null: false 4 t.text "content", null: false 5 t.index ["post_id"], name: "index_comments_on_post_id" 6 t.index ["user_id"], name: "index_comments_on_user_id" 7 end 8 9 create_table "posts", force: :cascade do |t| 10 t.text "content", null: false 11 t.integer "user_id" 12 t.index ["title", "content"], name: "index_posts_on_title_and_content" 13 t.index ["user_id"], name: "index_posts_on_user_id" 14 end 15 16 create_table "users", force: :cascade do |t| 17 t.string "email", null: false 18 t.string "password_digest", null: false 19 t.index ["first_name", "last_name"], name: "index_users_on_first_name_and_last_name" 20 end

usermodel

1 has_many :comments 2 has_many :posts

postmodel

1 belongs_to :user 2 has_many :comments

commentmodel

1 belongs_to :user 2 belongs_to :post

■view

postsshow

1<%= form_with model: [@post, @comment] do |f| %> 2 <%= hidden_field_tag :user_id, @current_user.id %> 3 <%= hidden_field_tag :post_id, @post.id %> 4 <%= f.text_field :content %> 5 <%= f.submit "保存", class: "btn" %> 6<% end %>

■コントローラ

applicationcontroller

1 before_action :set_current_user 2 3 def set_current_user 4 @current_user = User.find_by(id: session[:user_id]) 5 end

postscontroller

1 def show 2 @post = Post.find_by(id: params[:id]) 3 @comment = Comment.new 4 @user = User.find_by(id: @post.user_id) 5 end

commentscontroller

1 def create 2 @comment = Comment.create(comment_params) 3 @post = Post.find_by(id: params[:id]) 4 5 if @comment.save 6 flash.notice = "コメントを作成しました" 7 redirect_to post_path(@post) 8 end 9 end 10 11 def comment_params 12 params.require(:comment).permit(:content).merge(user_id: @current_user.id, 13 post_id: @post.id) 14 end

回答いただきたいこと

①エラー原因と対処について
なぜエラーが起きているのか(なぜpost_idが受け取れないのか)の原因と対処方法を回答いただだきたいです。

※かなり初歩的な認識違いかもしれませんが、以下のような認識でおり、エラーの原因について見当がつきませんでした。


controller/posts_controller.rbとview/posts/show.html.erbの中でそれぞれ以下のように書かれている。

def show
@post = Post.find_by(id: params[:id])
end

<%= form_with model: [@post, @comment] do |f| %>
<%= hidden_field_tag :post_id, @post.id %>
<%= f.submit "保存", class: "btn" %>
<% end %>

ルーティングはresources :postsで、URLはhttps://hoge/posts/:idのようになり、
show.html.erbではPost.find_by(id: params[:id])でURLの:idの値で、@postに値が入るはずである。


②エラー画面の情報について
エラー画面のRequest Parameters:のところを見るとpost_idの値が入っているように見えますが、
これはどのように解釈すればよろしいでしょうか?

補足情報(FW/ツールのバージョンなど)

■環境
・cloud9(Amazon Linux2)、※ローカルPCはWin10
・Rails 5.2.6
・ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]

■その他
・userはdeviseは使用せず、一から作成しています。
・プログラミング学習を始めてから4か月程の初学者です。
・不足している情報があればご指摘いただけますと幸いです。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

viewには、<%= hidden_field_tag :post_id, @post.id %>と書いてありますね。

ということは、paramsの中には、post_idというキー名でデータが入っているはずです。

それを考えると、
Post.find_by(id: params[:id])
ではなく、
Post.find_by(id: params[:post_id])なら取得できるかもしれないと思いました。


補足

もう一点。

comment_paramsが、@postの宣言より前に呼び出されているので、@postnilになっている可能性もありそうです。
comment_params内で@postが必要なのであれば、@postの宣言は、comment_paramsを使用する前に行うか、又は、comment_paramsメソッド内の初めに@postを宣言してしまってもよいかもしれませんね。

投稿2021/05/23 21:00

編集2021/05/23 21:03
siruku6

総合スコア1382

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

keigo555

2021/05/24 00:17

ご回答ありがとうございます。お蔭様で解決しました。大変助かりました。補足で記載いただいたように、comment_paramsの冒頭に@post = Post.find_by(id: params[:post_id])を書くことで動きました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問