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

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

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

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

Q&A

2回答

2698閲覧

アソシエーションで関連付けたテーブルのid(2つ)をうまく取得できない

mamikko

総合スコア7

Ruby on Rails

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

0グッド

0クリップ

投稿2020/05/20 14:49

編集2020/05/22 05:25

オリジナルアプリで商品のレビューページを作成中ですが、アソシエーションで関連づけたusers.idとproduct.idをnewページからcreateした時に、うまくDBに格納できません。privateメソッドにmargeで追加してみたりしましたが引数の渡し方に問題があるのか、うまく格納できません。ご教授頂けたらと思います。

user model

has_many :products, dependent: :destroy has_many :reviews, dependent: :destroy

product model

belongs_to :user has_many :reviews, dependent: :destroy

review model

belongs_to :user belongs_to :product

reviews_controller

def new @product = Product.find(params[:id]) @review = Review.new end  def create review = Review.new(review_params) if review.save redirect_to products_path, notice: "保存が成功しました" else render action: :new, notice: "保存が失敗しました" end end private def review_params params.require(:review).permit(:total, :package, :price, :color, :amount, :naming, :concept, :balance, :comment).merge(user_id: @current_user.id, product_id: params[:product_id]) end

new.html.erb

<h1>Review sheets</h1> <%= flash[:notice] %> <%= form_with model: @product,@review do |f| %> <div><%= f.label :'総合' %><div> <div><%= f.radio_button :total, "1" %> 1<div> <div><%= f.radio_button :total, "2" %> 2<div> <div><%= f.radio_button :total, "3" %> 3<div> <div><%= f.radio_button :total, "4" %> 4<div> <div><%= f.radio_button :total, "5" %> 5<div> <div><%= f.label :'パッケージ' %><div> <div><%= f.radio_button :package, "1" %> 1<div> <div><%= f.radio_button :package, "2" %> 2<div> <div><%= f.radio_button :package, "3" %> 3<div> <div><%= f.radio_button :package, "4" %> 4<div> <div><%= f.radio_button :package, "5" %> 5<div> <div><%= f.label :'価格' %><div> <div><%= f.radio_button :price, "1" %> 1<div> <div><%= f.radio_button :price, "2" %> 2<div> <div><%= f.radio_button :price, "3" %> 3<div> <div><%= f.radio_button :price, "4" %> 4<div> <div><%= f.radio_button :price, "5" %> 5<div> <div><%= f.label :'カラー' %><div> <div><%= f.radio_button :color, "1" %> 1<div> <div><%= f.radio_button :color, "2" %> 2<div> <div><%= f.radio_button :color, "3" %> 3<div> <div><%= f.radio_button :color, "4" %> 4<div> <div><%= f.radio_button :color, "5" %> 5<div> <div><%= f.label :'量・大きさ' %><div> <div><%= f.radio_button :amount, "1" %> 1<div> <div><%= f.radio_button :amount, "2" %> 2<div> <div><%= f.radio_button :amount, "3" %> 3<div> <div><%= f.radio_button :amount, "4" %> 4<div> <div><%= f.radio_button :amount, "5" %> 5<div> <div><%= f.label :'ネーミング' %><div> <div><%= f.radio_button :naming, "1" %> 1<div> <div><%= f.radio_button :naming, "2" %> 2<div> <div><%= f.radio_button :naming, "3" %> 3<div> <div><%= f.radio_button :naming, "4" %> 4<div> <div><%= f.radio_button :naming, "5" %> 5<div> <div><%= f.label :'コンセプト' %><div> <div><%= f.radio_button :concept, "1" %> 1<div> <div><%= f.radio_button :concept, "2" %> 2<div> <div><%= f.radio_button :concept, "3" %> 3<div> <div><%= f.radio_button :concept, "4" %> 4<div> <div><%= f.radio_button :concept, "5" %> 5<div> <div><%= f.label :'バランス' %><div> <div><%= f.radio_button :balance, "1" %> 1<div> <div><%= f.radio_button :balance, "2" %> 2<div> <div><%= f.radio_button :balance, "3" %> 3<div> <div><%= f.radio_button :balance, "4" %> 4<div> <div><%= f.radio_button :balance, "5" %> 5<div> <div><%= f.label :'コメント' %></div> <div><%= f.text_field :comment %></div> <div><%= f.hidden_field_tag :product_id, @product.id %></div> <div><%= f.submit "レビューする" %></div> <% end %> <div><%= link_to "トップページ", products_path %></div>
エラーコード Started POST "/reviews" for ::1 at 2020-05-21 11:01:42 +0900 Processing by ReviewsController#create as JS Parameters: {"utf8"=>"✓", "authenticity_token"=>"HiH793Sir412NVnz6Gs9R6/AIPH0nwLZG/MHrTuntsZn8xvcwEAMbqY9jLNAPo6sSeDfPk8AidgHahkG9DrFtg==", "review"=>{"total"=>"1", "package"=>"3", "price"=>"2", "color"=>"2", "amount"=>"1", "naming"=>"5", "concept"=>"5", "balance"=>"5", "comment"=>"aaaaaaaaa"}, "commit"=>"レビューする"} User Load (0.5ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 ↳ app/controllers/application_controller.rb:4 (0.4ms) BEGIN ↳ app/controllers/reviews_controller.rb:16 CACHE User Load (0.0ms) SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1 [["id", 2], ["LIMIT", 1]] ↳ app/controllers/reviews_controller.rb:16 (0.5ms) ROLLBACK ↳ app/controllers/reviews_controller.rb:16 Rendering reviews/new.html.erb within layouts/application Rendered reviews/new.html.erb within layouts/application (17.2ms) Completed 200 OK in 82ms (Views: 69.7ms | ActiveRecord: 1.4ms)
ログ ActionView::Template::Error (undefined method `id' for nil:NilClass): 54: <div><%= f.submit "レビューする" %></div> 55: <% end %> 56: <div><%= link_to "トップページ", products_path %></div> 57: <%= hidden_field_tag :product_id, @product.id %> app/views/reviews/new.html.erb:57:in `_app_views_reviews_new_html_erb___2040207276415451298_70112480660040' app/controllers/reviews_controller.rb:20:in `create'

review.save!にした時のログ

app/views/reviews/new.html.erb:57:in _app_views_reviews_new_html_erb___2040207276415451298_70112480660040' app/controllers/reviews_controller.rb:20:in create'
Started POST "/reviews" for ::1 at 2020-05-21 22:08:48 +0900
(0.2ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
↳ /Users/mami.igarashi/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.4.2/lib/active_record/log_subscriber.rb:98
Processing by ReviewsController#create as JS
Parameters: {"utf8"=>"✓", "authenticity_token"=>"HiH793Sir412NVnz6Gs9R6/AIPH0nwLZG/MHrTuntsZn8xvcwEAMbqY9jLNAPo6sSeDfPk8AidgHahkG9DrFtg==", "review"=>{"total"=>"5", "package"=>"3", "price"=>"2", "color"=>"2", "amount"=>"1", "naming"=>"5", "concept"=>"5", "balance"=>"5", "comment"=>"aaaaaaaaa"}, "commit"=>"レビューする"}
User Load (0.3ms) SELECT users.* FROM users WHERE users.id = 2 LIMIT 1
↳ app/controllers/application_controller.rb:4
(0.2ms) BEGIN
↳ app/controllers/reviews_controller.rb:17
CACHE User Load (0.0ms) SELECT users.* FROM users WHERE users.id = 2 LIMIT 1 [["id", 2], ["LIMIT", 1]]
↳ app/controllers/reviews_controller.rb:17
(0.2ms) ROLLBACK
↳ app/controllers/reviews_controller.rb:17
Completed 422 Unprocessable Entity in 54ms (ActiveRecord: 6.8ms)

ActiveRecord::RecordInvalid (Validation failed: Product must exist, Product can't be blank):

app/controllers/reviews_controller.rb:17:in `create'

application_controller

class ApplicationController < ActionController::Base
before_action :set_current_user
def set_current_user
@current_user = User.find_by(id: session[:user_id])
end
end

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

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

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

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

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

winterboum

2020/05/20 23:12

new の viewを載せてください
mamikko

2020/05/20 23:27

newのviewファイルを掲載しました。5段階評価のページにしようと思ってライジオボタンで作成しました。
guest

回答2

0

current_user が Productを選んで、そこでReview作製 すると reviews_controller の newが呼ばれ、new.html.erbが表示されてsubmitするとreviews_controllerのcreateが実行される

という流れの前提で書きます。
(そういうことを「想像」させないですむ質問が書けるようになってください)
Reviewの作製には 誰が何についての情報が必要です。
誰が は login情報から取れますが何についてはviewからのparamsになければなりません。
@product = Product.find(params[:id]) となっててあたかもproductを得ているかのようですが、logでparams確認してください。idは無いと思います。
params[:id]と書けば無敵の召喚呪文の如くその時欲しいものが手に入るわけではないです。
reviews_controller の newが書かれていないので(こんなことを書かなくて済む質問が書けるようになってください)??ですがここで
@product = Product.find(params[:id])して(前提、newを呼ぶviewがidを渡していること)
newのviewにて
hidden_field_tag :product_id, @product.id
してください。
で、review_paramsを
params.require(:review).permit(、、、、、).merge(product_id: params[:product_id], user_id: current_user.id)

変更点多いのであまり厳密に見ていません。
うまく行かなかったら
controller の new、それを呼び出す view、logを載せてください

修正内容
merge(product_id: params[:product_id] となっていたので、idをproduct_idにしゅうせい

更に追記
save!にて「Product must exist,」 すなわち product_id がnilもしくは実在しないid

reviews_controller#review_params の product_id: params[:product_id]のparams[:product_id]が怪しい

new.html.erb の %= f.hidden_field_tag :product_id, @product.id %> の @product があやしい

controller#new の @product = Product.find(params[:id]) の params[:id が怪しい

new.htmlが何の id を渡しているのか

new.htmlを起動しているcontrollerは idのために new.htmlにどんな値をわたしているのか

Boldなところの情報が必要です

投稿2020/05/21 02:07

編集2020/05/22 04:24
winterboum

総合スコア23567

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

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

mamikko

2020/05/21 13:07

説明不足の質問で申し訳ありません。丁寧な解答ありがとうございます。controllerのnew に```@product = Product.find(params[:id])```して、newのviewにて ```hidden_field_tag :product_id, @product.id```を追記しましたが、うまくproduct_idを得ることができないようです。 修正内容 merge(product_id: params[:product_id] となっていたので、idをproduct_idにしゅうせい ↑はproduct_idだとnonameエラーになり、@product_idに修正して入力しています。
winterboum

2020/05/21 13:30 編集

回答に書いてある以下のやってないんでは? 前提が重要 @product = Product.find(params[:id])して(前提、newを呼ぶviewがidを渡していること)
mamikko

2020/05/21 13:40

@product = Product.find(params[:id])はcontrollerのnewに追記しましたが、間違っていますか?
winterboum

2020/05/21 20:53

前提、newを呼ぶviewがidを渡していること は確認しました?
guest

0

rb

1def create 2 review = Review.new(review_params) 3 @product = Product.find(params[:id]) 4 @reviews = @Product.reviews 5 if review.save 6 redirect_to products_path, notice: "保存が成功しました" 7 else 8 render action: :new, notice: "保存が失敗しました" 9 end 10 end 11 12 private 13 def review_params 14 params.require(:review).permit(:total, :package, :price, :color, :amount, :naming, :concept, :balance, :comment) 15 end

ここに出てくるreviewに対してuser_idproduct_idを格納できないという話でよろしいですか?

このreviewが生成されてからreview.saveされるまでの間にuser_idproduct_idを渡すような処理がどこにも書かれていないように見えます。
reviewsテーブルにuser_idproduct_idを格納するカラムが用意されているのであれば、値を渡す処理を書き加えれば意図した動作をすると思います。

privateメソッドにmargeで追加してみたりしましたが

これのやり方が正しければそれで解決しそうに思えますが、これを質問内に記述していないのはどうしてですか?
追記されていたようなので訂正します。

ロールバックが起きる原因がわからないので例外をログに出力してもらえますか?
review.save!のようにsaveの後ろに!をつけるとログに例外が出力されるようになります。


ログの内容とコードの内容が合ってなかったり、エラーが起きるはずのコードでエラーが起きてないなど、ちょっとこれ以上はわかりかねるので、こんな感じで書けば動くんじゃないかなというサンプルを述べておきます。参考にしてください。

def new @product = Product.find(params[:id]) @review = @product.reviews.new # 関連レコードはこのように作成すれば product_id は不要。 end  def create # render action: :new した場合には @product が必要 # form_with model: [@product, @review] で送信したら product のIDは params[:product_id] にあるのが普通 @product = Product.find(params[:product_id]) # render action: :new した場合には @review が必要 @review = @product.reviews.new(review_params) if @review.save redirect_to products_path, notice: "保存が成功しました" else render action: :new, notice: "保存が失敗しました" end end private def review_params params.require(:review).permit(:total, :package, :price, :color, :amount, :naming, :concept, :balance, :comment).merge(user_id: @current_user.id) end

erb

1<h1>Review sheets</h1> 2<%= flash[:notice] %> 3<%# model: に複数のオブジェクトを渡す際は [] で囲う必要があると思うけどエラーはない? %> 4<%= form_with model: [@product, @review] do |f| %> 5 ... 6 <div><%= f.label :'コメント' %></div> 7 <div><%= f.text_field :comment %></div> 8 <div><%= f.submit "レビューする" %></div> 9 <%# 前述の通り product_id は不要 %> 10<% end %> 11 <div><%= link_to "トップページ", products_path %></div>

投稿2020/05/21 02:07

編集2020/05/22 06:03
Mugheart

総合スコア2349

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

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

mamikko

2020/05/21 13:17 編集

分かりにくい質問の中、解答をありがとうございます。newのviewにhidden_field_tag :product_id, @product.id`を追記してreview.save!にしてログを出力してみました。user_idは渡されているようですが、product_idがうまく渡されていないようです。
Mugheart

2020/05/22 00:05

hidden_field_tag :product_id というのをフォームの外に書いているから送信されてないのでは?
mamikko

2020/05/22 03:56

フォームの中に入れてみたんですが、何も変わらす。product_idだけが渡されません。(TT)
Mugheart

2020/05/22 04:09

<div><%= f.hidden_field_tag :product_id, @product.id %></div> はNoMethodErrorになると思うんですが、書き間違い等はないですか?
mamikko

2020/05/22 04:34

ログにはActiveRecord::RecordInvalid (Validation failed: Product must exist, Product can't be blank): と出てきます。書き間違いはないと思うんですが。。もともとproduct_idとuser_idは紐づいていても一緒には取得できないんですね?本当に無知すぎて申し訳ないです。
mamikko

2020/05/22 07:22

すごくわかりやすい解答例ありがとうございます! コントローラーの def new @product = Product.find(params[:id])←毎回ここの部分にエラーが出てしまうんですよね。 @review = @product.reviews.new end エラー ActiveRecord::RecordNotFound in ReviewsController#new Couldn't find Product without an ID
mamikko

2020/05/22 07:29

もう少し自分でも調べてみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問