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

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

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

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

Ruby on Rails

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

Q&A

解決済

2回答

1235閲覧

【Rails】form_withでのデータ新規登録処理時、NoMethodErrorが出て処理が失敗する

otdsh9432

総合スコア55

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2020/07/04 09:34

編集2020/07/04 09:36

実現したいこと

form_withを用いて新規投稿を行う画面処理を実装したいです。

事象・困っていること

画面でformの各項目を入力し、更新ボタンを押下したところ、
「NoMethodError in Posts#create undefined method `where' for nil:NilClass」
という表示が出て、処理が失敗してしまいます。
エラー画面キャプチャ

エラーメッセージに含まれる「where」は、collection_selectで、formにてプルダウンリストを表示させるため、
コードマスタからwhereで条件に合うコードリストを取ってきている箇所で使用しています。
(<%= f.collection_select :area, code.where(code_id: "1"), :code, :name %>)

画面表示時は、この部分でエラーはなくプルダウンリストも表示されます。
しかし、更新ボタンを押下後のみエラーが出るのがなぜなのかわからない状態です。

form_withの仕組みをより詳しく知る必要があるかと思い調査中ですが、
なかなか原因がわからず、かなり時間がかかっているため、ご質問した次第です。

エラーが起きた背景

下記のように、ルーティングをネストしており、
communityというモデルの配下に、postというモデルを配置しています。
(今回のフォームは、postに対するデータ登録です)

Ruby

1 resources :communities do 2 resources :posts do 3 end

→もともとは、postモデルのみ存在していました(ネストしていませんでした)。
その際はform_withからの登録処理は正常に動作していました。
しかし、最近、communityモデルを新設し、postをネストしました。
それに伴い、form_withも下記の通りネストに対応させた形に修正しました。
(model:とurl:を分けて、urlを明記した形)

Ruby

1<%= form_with(model: post, url: [community,post] ,local:true) do |f| %>

新規投稿フォーム(new.html.erb、_form.html.erb)

<new.html.erb>

Ruby

1<h3>お店を登録する</h3> 2 <div class="post-form"> 3 <%= render partial:'form', locals:{post: @post, code: @code, community: @community} %> 4 </div>

<_form.html.erb>※関連部分のみ抜粋

Ruby

1<%= form_with(model: post, url: [community,post] ,local:true) do |f| %> 2 <div class="form-group"> 3 <%= f.label "店名" %> 4 <%= f.text_field :title, class:'form-control', id: 'title_name' %> 5 </div> 6 <div class="form-group"> 7 <%= f.label "都道府県" %><br> 8 <%= f.collection_select :prefecture_code, JpPrefecture::Prefecture.all, :code, :name, {include_blank: '都道府県を選択してください'}, {class: "form-control"} %> 9 </div> 10 <div class="form-group"> 11 <%= f.label "エリア" %><br> 12 <%= f.collection_select :area, code.where(code_id: "1"), :code, :name, {include_blank: 'エリアを選択してください'}, {class: "form-control"} %> 13 </div> 14 <div class="form-group"> 15 <%= f.label "料理ジャンル" %><br> 16 <%= f.collection_select :rest_type, code.where(code_id: "2"), :code, :name, {include_blank: '料理ジャンルを選択してください'}, {class: "form-control"} %> 17 </div> 18 <%= f.hidden_field :community_id, value: community.id %> 19 <%= f.submit "更新する", class:'btn btn-primary' %> 20 <%= link_to '戻る', community_posts_path(community), class:'btn' %> 21<% end %>

コントローラ(posts_controller.rb)※関連部分のみ抜粋

Ruby

1class PostsController < ApplicationController 2 3 def new 4 @community = Community.find_by(params[:community_id]) 5 @post = Post.new 6 @code = Code.all 7 end 8 9 def create 10 @post = current_user.posts.build(post_params) 11 12 if @post.save 13 redirect_to communities_url, notice:"お店「#{@post.title}」を登録しました。" 14 else 15 render :new 16 end 17 end 18 19 private 20 21 def post_params 22 params.permit(:title, :area, :prefecture_code, :rest_type, :community_id) 23 end 24 25end

ルーティング(routes.rb)※関連部分のみ抜粋

Ruby

1Rails.application.routes.draw do 2 3 resources :communities do 4 resources :posts do 5 end 6 7end

コードマスタ(schema.rb)※抜粋

Ruby

1 create_table "codes", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci", force: :cascade do |t| 2 t.string "code_id", null: false 3 t.string "sub_id", null: false 4 t.string "code", null: false 5 t.string "name" 6 t.datetime "created_at", null: false 7 t.datetime "updated_at", null: false 8 t.index ["code_id", "sub_id", "code"], name: "index_codes_on_code_id_and_sub_id_and_code", unique: true 9 end

不足情報等ございましたら、お手数をお掛けし恐れ入りますが、
ご指摘いただけますと幸いです。
何卒よろしくお願い申し上げます。

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

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

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

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

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

guest

回答2

0

自己解決

自己解決しました。以下2点修正しました。
①form_withの記述を修正
誤:<%= form_with(model: post, url: [community,post] ,local:true) do |f| %>
正:<%= form_with(model: [community,post] ,local:true) do |f| %>
→「url:」を指定してしまうと、データを保存しないフォームとして扱われてしまい、
データ更新時に、データが保存されるのではなく、単にリダイレクトのみ行われてしまうため。
https://pikawaka.com/rails/form_with

②posts_controller.rbのストロングパラメータの記述を修正。
誤:params.permit(:title, :area, :prefecture_code, :rest_type, :community_id)
正:params.require(:post).permit(:title, :area, :prefecture_code, :rest_type, :community_id)
form_withで送信された通信は、指定したモデル(post)のキー値であるPOST通信となっているため、
ストロングパラメータでもキー値を指定し、正しくパラメータを受け取れるようにする必要がある。

投稿2020/07/04 13:59

編集2020/07/04 14:02
otdsh9432

総合スコア55

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

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

0

code.whereCode.where

投稿2020/07/04 10:28

winterboum

総合スコア23329

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

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

otdsh9432

2020/07/04 13:28

winterboum 様 ご回答いただきありがとうございます。 Code.whereにするとその箇所のエラーはなくなりましたが、新たなエラーが出ました。 <%= f.hidden_field :community_id, value: community.id %>の箇所で、 communityがnullであるとのエラーです。 ここについて、先述したcodeでも同じなのですが、 new.html.erbからパーシャル(_form.html.erb)へ、codeやcommunityも渡しているため、 nullとなる原因がわかりません。 (new.html.erbの locals:{post: @post, code: @code, community: @community}の箇所) 恐れ入りますが、こちらの原因についてご教示いただけないでしょうか。 並行して私自身でも調査中ではありますが、よろしくお願いいたします。
winterboum

2020/07/04 22:40

_form のほうだけみてました、すみません。 @community = Community.find_by(params[:community_id]) の方は newを呼ぶ時に正しく community_id が渡っていない可能性があります。logで確認してみてください。 ただそれでは postとcommunityのほうが謎のまま。 ちょっと気になるのは locals:{..} と :と{の間に空白が無いこと。ここでインタプリタが解釈間違えている可能性がないか、、、
otdsh9432

2020/07/05 07:13 編集

ご返信いただきありがとうございます。 >newを呼ぶ時に正しく community_id が渡っていない →まさにこちらが原因の一つであり、ストロングパラメータの記述方法が誤っておりました。(パラメータのキー値が未設定でした)localsの方は問題なく動作できました。 ご回答戴いた内容をもとに、自己解決に辿り着くことができました。お手数をお掛けしました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問