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

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

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

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

Q&A

解決済

4回答

2148閲覧

NoMethodError in Comments#create を解消したい

sinatra

総合スコア0

Ruby on Rails

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

0グッド

1クリップ

投稿2021/07/18 04:56

前提・実現したいこと

Ruby on Railsで画像投稿とそれに対するコメント投稿ができるアプリケーションを実装中です。画像投稿機能の実装が終わり、コメント投稿機能の実装中に以下のエラーが発生しました。

エラーの内容を把握し、同じようなエラーが出たときに、考察できるようになりたい。
エラーメッセージの「titleがNilに対して定義されていない」という意味がどういうことなのか、理解しバグを見つけたい。

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

Showing /Users/ruth/projects/protospace-35643/app/views/prototypes/show.html.erb where line #5 raised: undefined method `title' for nil:NilClass Extracted source (around line #5): 3 <div class="prototype__wrapper"> 4  <p class="prototype__hedding"> 5   <%= @prototype.title %>           <---- ここ 6  </p> 7  <%= link_to "by #{@prototype.user.name}", prototype_path(@prototype.user.id), class: :prototype__user %> 8 <%# プロトタイプの投稿者とログインしているユーザーが同じであれば以下を表示する %>

該当のソースコード

routes.rb

Rails.application.routes.draw do devise_for :users root to: "prototypes#index" resources :users, only: :show resources :prototypes do resources :comments, only: :create end end

prototypes_controller.rb

before_action :set_prototype, only: [:edit, :show] before_action :move_to_index, except: [:index, :show] def index @prototypes = Prototype.includes(:user) end def new @prototype = Prototype.new end def create @prototype = Prototype.new(prototype_params) if @prototype.save redirect_to root_path else render :new end end def show @comment = Comment.new @comments = @prototype.comments.includes(:user) end def destroy @prototype = Prototype.find(params[:id]) if @prototype.destroy redirect_to root_path end end def edit end def update @prototype = Prototype.find(params[:id]) if @prototype.update(prototype_params) redirect_to prototype_path(@prototype.id) else render :edit end end private def prototype_params params.require(:prototype).permit(:title, :catch_copy, :concept, :image, :user_id).merge(user_id: current_user.id) end def set_prototype @prototype = Prototype.find(params[:id]) end def move_to_index unless user_signed_in? redirect_to action: :index end end end

comments_contoroller.rb

def create @comment = Comment.new(@comment_params) if @comment.save redirect_to action: :show else render template: "prototypes/show" end end private def comment_params params.require(:comment).permit(:text).merge(user_id: current_user.id, prototype_id: params[:prototype_id]) end end

prototypes/show.html.erb

<main class="main"> <div class="inner"> <div class="prototype__wrapper"> <p class="prototype__hedding"> <%= @prototype.title %> </p> <%= link_to "by #{@prototype.user.name}", prototype_path(@prototype.user.id), class: :prototype__user %> <%# プロトタイプの投稿者とログインしているユーザーが同じであれば以下を表示する %> <% if user_signed_in? && current_user.id == @prototype.user_id%> <div class="prototype__manage"> <%= link_to "編集する", edit_prototype_path(@prototype.id), class: :prototype__btn %> <%= link_to "削除する", prototype_path(@prototype.id), method: :delete, class: :prototype__btn %> </div> <% end %> <%# // プロトタイプの投稿者とログインしているユーザーが同じであれば上記を表示する %> <div class="prototype__image"> <%= image_tag @prototype.image, class: :card__img %> </div> <div class="prototype__body"> <div class="prototype__detail"> <p class="detail__title">キャッチコピー</p> <p class="detail__message"> <%= @prototype.catch_copy %> </p> </div> <div class="prototype__detail"> <p class="detail__title">コンセプト</p> <p class="detail__message"> <%= @prototype.concept %> </p> </div> </div> <div class="prototype__comments"> <%# ログインしているユーザーには以下のコメント投稿フォームを表示する %> <% if user_signed_in? %> <%= form_with model: [@prototype, @comment],local: true do |f|%> <div class="field"> <%= f.label :text, "コメント" %><br /> <%= f.text_field :text, id:"comment_text" %> </div> <div class="actions"> <%= f.submit "送信する", class: :form__btn %> </div> <% end %> <% end %> <%# // ログインしているユーザーには上記を表示する %> <ul class="comments_lists"> <%# 投稿に紐づくコメントを一覧する処理を記述する %> <% @comments.each do |comment| %> <li class="comments_list"> <%= comment.text %> </li> <%= link_to comment.user.name, "/users/#{comment.user_id}", class: :comment_user %> <% end %> <%# // 投稿に紐づくコメントを一覧する処理を記述する %> </ul> </div> </div> </div> </main>

試したこと

1スペルミスのチェック
2ルーティングができているか
3モデル同士のアソシエーションができているか
4comments_controller.rbのredirect_toとrenderのメソッドが定義されているか
5comments_controller.rbのcreateメソッド内で呼び出すファイルの定義はあっているか

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

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答4

0

パイロットプログラムは非常に興味深いものです。 ただし、最適な開発を確実に行うためには、適切な情報セキュリティを確保してください。 この成功は大衆を容易に惹きつける snake io

投稿2023/10/30 02:12

Okerag

総合スコア2

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

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

0

自己解決

解決方法

prototypes_controller.rbのshowアクションを以下のように編集

def show @comment = Comment.new @comments = @prototype.comments end

comments_controller.rbのif文else以下、render前に

@prototype = @comment.prototype @comments = @prototype.comments

を追加し解決しました。

投稿2021/07/20 21:38

sinatra

総合スコア0

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

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

0

なんかおかしいですね。
<%= @prototype.title %> で @prototypeがnilだと言われるなら、そこに行く前に def showの@comments = @prototype.comments.includes(:user) でエラーになってます。

エラーの起きたときと、載せている code と全く一緒ですか?

投稿2021/07/18 22:22

winterboum

総合スコア23567

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

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

sinatra

2021/07/19 04:02 編集

winterboum様、ご回答ありがとうございます。 質問を投稿してから1つ変更したところがあり、その状態でも全く同じエラー文が出ています。 変更したのはcomments_controllerで redirect_to prototype_path(@comment.prototype) としました。 binding.pryをcreateのすぐ下にかけて、内容をみてみたところ以下のように表示されました。 2: def create => 3: binding.pry 6: @comment = Comment.new(@comment_params) 7: if @comment.save 8: redirect_to prototype_path(@comment.prototype) 9: else 10: render template: "prototypes/show" 11: end 12: end [1] pry(#<CommentsController>)> @comment = Comment.new(@comment_params) => #<Comment:0x00007f86a40d3338 id: nil, text: nil, user_id: nil, prototype_id: nil, created_at: nil, updated_at: nil> [2] pry(#<CommentsController>)> params => <ActionController::Parameters {"authenticity_token"=>"acJqUF/BeU9U+rUDOT+/NfnwcGpN5th9W079NO5TBQPR84HDRJLD4P7xLtQQ9Aag2z4iDNDoWNb9m9P2rEtG6g==", "comment"=>{"text"=>"comment test"}, "commit"=>"送信する", "controller"=>"comments", "action"=>"create", "prototype_id"=>"1"} permitted: false> [3] pry(#<CommentsController>)> @comment.save => false
winterboum

2021/07/19 02:35 編集

ああ、createのときの問題ね、viewがshowだからshowのときかと思った。 発生状況を正しく伝えないと正しい答えは得られません
winterboum

2021/07/19 03:07

はて やはり変だ create 失敗すると newのviewに行くはずなのに、エラーはshow。 エラーが起きたときのcodeになおし どういう手順でエラーが起きたのかを説明し エラーメッセージを全文載せる ようにしてください
sinatra

2021/07/19 04:22 編集

初めて投稿し、要領がわかっておらず、お手数おかけしてすいません。。 エラーが起きた時のコードに直し、以下が現在のエラーメッセージです。 エラーが起きた時の手順としては、画像とキャッチコピーなどを投稿・保存した後、投稿された画像をクリックするとその詳細に遷移するように実装しました。詳細画面からコメント投稿ができるように実装しようとしている段階で、コメントを入力し送信をクリックしたところで以下のエラーメッセージが出た、という感じです。 NoMethodError in Comments#create undefined method `title' for nil:NilClass Extracted source (around line #5): 3 <div class="prototype__wrapper"> 4 <p class="prototype__hedding"> 5 <%= @prototype.title %> 6 </p> 7 <%= link_to "by #{@prototype.user.name}", prototype_path(@prototype.user.id), class: :prototype__user %> 8 <%# プロトタイプの投稿者とログインしているユーザーが同じであれば以下を表示する %> Application Trace | Framework Trace | Full Trace app/views/prototypes/show.html.erb:5 app/controllers/comments_controller.rb:9:in `create' Request Parameters: {"authenticity_token"=>"gHaTL+uXY85AQ1P9Rt4MPma0BineNOMO04pEH3Cpyz84R3i88MTZYepIyCpvFbWrRHpUT0M6Y6V1X2rdMrGI1g==", "comment"=>{"text"=>"comment test"}, "commit"=>"送信する", "prototype_id"=>"5"}
winterboum

2021/07/19 05:17

create の elseで、render template: "prototypes/show" の前に @prototype を定義してください
sinatra

2021/07/20 21:38

ありがとうございました。解決致しました。
guest

0

@prototypeの中身はどうなっていますか?
set_prototypeメソッドで@prototypeの情報は取れているかと思いますが、
デバック等で中身を確認してみてください。
またshowアクションに移動する前のlink_toメソッドでprototypeのidをちゃんと渡せているかも確認してみてください。

投稿2021/07/18 14:07

J_O

総合スコア143

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

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

sinatra

2021/07/19 03:47

J_O様、ご回答ありがとうございます。 binding.pryで@prototypeの中身を確認したところ@prototypeの情報は取れている感じでした。 その後showアクションの@comment = Comment.newを入力するとprototype_idとuser_idがnilになっていたので、それが渡せていない?のが原因でしょうか? 補足 [5] pry(#<PrototypesController>)> @prototype => #<Prototype:0x00007f9ef9aa8558 id: 5, title: "binding.pry", catch_copy: "test", concept: "test", user_id: 2, created_at: Mon, 19 Jul 2021 03:33:35 UTC +00:00, updated_at: Mon, 19 Jul 2021 03:33:35 UTC +00:00> [6] pry(#<PrototypesController>)> @prototype = Prototype.find(params[:id]) ActiveRecord::RecordNotFound: Couldn't find Prototype without an ID from /Users/ruth/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/activerecord-6.0.4/lib/active_record/relation/finder_methods.rb:431:in `find_with_ids' [7] pry(#<PrototypesController>)> prototype_params => <ActionController::Parameters {"title"=>"binding.pry", "catch_copy"=>"test", "concept"=>"test", "image"=>#<ActionDispatch::Http::UploadedFile:0x00007f9ef8d7eb48 @tempfile=#<Tempfile:/var/folders/_r/8hsm1l9d3nbcmbb6qgl_mnpc0000gn/T/RackMultipart20210719-31830-wsu3p8.jpg>, @original_filename="Canva - Close Up Photo of Yellow Orange and Green Leaf Trees.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"prototype[image]\"; filename=\"Canva - Close Up Photo of Yellow Orange and Green Leaf Trees.jpg\"\r\nContent-Type: image/jpeg\r\n">, "user_id"=>2} permitted: true> [8] pry(#<PrototypesController>)> @comment = Comment.new => #<Comment:0x00007f9ef767ff00 id: nil, text: nil, user_id: nil, prototype_id: nil, created_at: nil, updated_at: nil>
J_O

2021/07/19 07:22 編集

なるほど、commentのcreate時のエラーだったんですね。 じゃあcommntはsaveされてないですよね? 下記仮説ですが、 そのsaveされてない原因が今回のエラーの原因っぽいです。 恐らくprototyeのidがsave時にnilの状態でsaveされなかったんだと思います。 そのため、"prototypes/show"にいったときに@prototypeの情報がないためエラーになっていると思われます。
sinatra

2021/07/20 21:39

ありがとうございます。何とか解決致しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問