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

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

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

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

Q&A

解決済

1回答

2670閲覧

Ruby on Railsでformで値を送信するが、保存されない

nissyan

総合スコア15

Ruby

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

0グッド

0クリップ

投稿2020/01/12 14:53

編集2020/01/15 00:23

Ruby on Railsでショッピングカート機能を実装しています。
商品一覧画面から、商品の個数を選択してcartテーブルに保存したい状況です。
※cartテーブルはsessionで仮に商品を保存するためのテーブルとなってます。

そして商品一覧indexのコントローラーで、cart.newを記述して、cartのコントローラーで
createメソッドに飛ばしています。

環境:
rails 5.2.3
gem devise機能を使用


ruby

1index前のコントローラーになります。 2class BoxlunchesController < ApplicationController 3 def index 4 @boxlunches = Boxlunch.all 5 @cart = Cart.new 6 end 7 8 def show 9 end 10end 11 12

課題:
商品一覧画面から、商品の個数(boxlunch_quantity)を選択し、formで値を送信するが、boxlunch_quantityのみ保存されない
※boxlunch_idはcart_itemテーブルに保存されます。

Ruby

1 index.html.haml 2 3 = render 'layouts/header' 4= render "./template/menu_selections" 5.menu-container 6 %h2 Boxlunch Menu 7 .menu-contents 8 - @boxlunches.each do |boxlunch| 9    #cart_index_pathでcartのcreateに飛びます 10 = form_for @cart, url: cart_index_path(boxlunch_id: boxlunch.id), method: :post do |f| 11 .menu-package 12 .menu-image 13 = link_to "boxlunch/#{boxlunch.id}" do 14 = image_tag boxlunch.image, width:"200px", height:"150px" 15 %h4 16 = link_to do 17 = boxlunch.name 18 .count-price-container 19 .count-price 20 .price 21 %p ¥#{boxlunch.price}(税込) 22 .count 23 %label 24 =f.select :boxlunch_quantity, options_for_select(1..10), include_blank: '0' 25 =f.submit "カートの中に入れる" 26= render 'layouts/footer'

エラー内容
ブラウザーではエラーは表示されていないので
ターミナルでの記載になります。

ruby

1ターミナル 2Started POST "/cart?boxlunch_id=1" for ::1 at 2020-01-13 23:49:36 +0900 3Processing by CartController#create as HTML 4 Parameters: {"utf8"=>"✓", "authenticity_token"=>"O5g+me6pcK+uueZYWtdRBmkFdj+TzXqkyZRyw+q5KvkcqQ3wGLzM05qi79LfoOL9vd7aI54B78hSBNdXYOML2A==", "cart"=>{"boxlunch_quantity"=>"1"}, "commit"=>"カートの中に入れる", "boxlunch_id"=>"1"} 5 Order Load (2.0ms) SELECT "orders".* FROM "orders" WHERE "orders"."id" IS NULL LIMIT $1 [["LIMIT", 1]] 6 ↳ app/controllers/application_controller.rb:16 7 (0.8ms) BEGIN 8 ↳ app/controllers/application_controller.rb:17 9 (1.1ms) ROLLBACK 10 ↳ app/controllers/application_controller.rb:17 11 Boxlunch Load (0.7ms) SELECT "boxlunches".* FROM "boxlunches" WHERE "boxlunches"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]] 12 ↳ app/controllers/cart_controller.rb:4 13 Order Load (1.6ms) SELECT "orders".* FROM "orders" WHERE "orders"."id" IS NULL LIMIT $1 [["LIMIT", 1]] 14 ↳ app/controllers/application_controller.rb:16 15 (1.8ms) BEGIN 16 ↳ app/controllers/application_controller.rb:17 17 (0.4ms) ROLLBACK 18 ↳ app/controllers/application_controller.rb:17 19 (1.0ms) BEGIN 20 ↳ app/controllers/cart_controller.rb:6 21 Cart Create (0.5ms) INSERT INTO "carts" ("boxlunch_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["boxlunch_id", 1], ["created_at", "2020-01-13 14:49:36.819147"], ["updated_at", "2020-01-13 14:49:36.819147"]] 22 ↳ app/controllers/cart_controller.rb:6 23 (1.9ms) COMMIT 24 ↳ app/controllers/cart_controller.rb:6 25 User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]] 26 ↳ app/controllers/cart_controller.rb:7 27Redirected to http://localhost:3000/cart/1 28Completed 302 Found in 46ms (ActiveRecord: 12.1ms) 29 30 31Started GET "/cart/1" for ::1 at 2020-01-13 23:49:36 +0900 32Processing by CartController#show as HTML 33 Parameters: {"id"=>"1"} 34 Rendering cart/show.html.haml within layouts/application 35 Rendered cart/show.html.haml within layouts/application (1.9ms) 36Completed 200 OK in 63ms (Views: 60.4ms | ActiveRecord: 0.0ms)

アプリケーションコントローラーのコード
※current_cartを定義しています。

ruby

1 class ApplicationController < ActionController::Base 2 protect_from_forgery with: :exception 3 before_action :authenticate_user! 4 5 6 def after_sign_in_path_for(resource) 7 root_path # ログイン後に遷移するpathを設定 8 end 9 10 def after_sign_out_path_for(resource) 11 root_path # ログアウト後に遷移するpathを設定 12 end 13 14 private 15 def current_cart 16 @current_cart = Order.find_by(id: session[:order_id]) 17 @current_cart = Order.create unless @current_cart 18 session[:order_id] = @current_cart.id 19 @current_cart 20 end 21end 22

![Model ER図改正]イメージ説明

カートのモデルコード

ruby

1class Cart < ApplicationRecord 2 belongs_to :order 3 has_many :boxlunches 4 5 6 def add_boxlunch(boxlunch_id) 7 cart.find_or_initialize_by(boxlunch_id: boxlunch_id) 8 end 9 10 def add_single_menu(single_menu_id) 11 cart.find_or_initialize_by(single_menu_id: single_menu_id) 12 end 13end

カートのコントローラーのコード

ruby

1class CartController < ApplicationController 2 def create 3 cart = current_cart 4 boxlunch = Boxlunch.find(params[:boxlunch_id]) 5 @cart = current_cart.add_boxlunch(boxlunch.id) 6 if @cart.save 7 redirect_to cart_path(current_user) 8 else 9 render :new 10 end 11 end 12 13 private 14 def cart_params 15 params.require(:cart).permit(:boxlunch_quantity); 16 end 17 end

以上のような状況です。
お忙しい中ですが、教えていただけますと助かります。

宜しくお願いいたします。

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

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

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

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

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

winterboum

2020/01/12 23:55

プログラム類は 逆シングルコーテーション3つの間にいれてインデントが判るようにしてください。 インデント命のhamlが、、、、 RUBYのcodeも読みにくい。 読みにくいと読んでもらえないので、回答がつきにくいです
nissyan

2020/01/13 09:07 編集

winterboumさん ご回答ありがとうございます。 ①order_idが代入されるのは、17行目のsession[:order_id] = @current_cart.id です。 loginの時に定義しておりません。 ②orderテーブルは、boxlunchとcart_itemの中間テーブルに位置するものです。 そして、logを撮った時とコードは同じです。 すみません!逆シングルコーテーション3つの間にいれてインデントが判るようにするということがわからないです。 ""を``に変更するということですか。  3つの間とはどうゆうことですか? 以上、ご確認よろしくお願いします。
nissyan

2020/01/13 10:44 編集

モデルの関係性をER図で書きましたので、一度ご確認していただけたら 嬉しいです。 cart_itemの方は、index.htmlに遷移する前のコントローラーで, cart_item.newをしています。 order.newも必要でしょうか? index.htmlの前のコントローラもコードを追記しておきます。 すみませんが、ご確認お願いいたします。
winterboum

2020/01/13 10:53

Boxlunch と Order をつなぐものが CartItemというのはいただけません。 CarItemという名前からは CartとItemをつなぐものと誤解されます、 これは直したほうがよい
winterboum

2020/01/13 11:11

OrderとAddressの関連はない方が自然です。 Addressが沢山Orderをもつとか、Orderがaddressに属するというのは不自然。 Orderの送り先という考えかと思いますが、OrderしたのはUser,そのaddressへ送ればよいのです
guest

回答1

0

ベストアンサー

application_controller.rb の 15,16,17行目ってこれですか?

@current_cart = Order.find_by(id: session[:order_id]) @current_cart = Order.create unless @current_cart session[:order_id] = @current_cart.id

この session[:order_id] が最初に代入されるのはいつ、どのfileのどのmethodでしょう?
もしかして この17行目?
すると最初に 15行目に来た時はまだ未定義ですから@carrent_cartはnilです。
もしかするとloginの時に定義してますか?
そこを確認してください

追記
不思議、、、、
(0.2ms) BEGIN
↳ app/controllers/cart_items_controller.rb:7
CartItem Create (0.9ms) INSERT INTO "cart_items" ("boxlunch_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["boxlunch_id", 2], ["created_at", "2020-01-12 14:54:40.381901"], ["updated_at", "2020-01-12 14:54:40.381901"]]
↳ app/controllers/cart_items_controller.rb:7
(0.5ms) COMMIT
とあるのでCartItemは作られています。ただ見て判るように order がなになのかわからない状態で。
ところが、CartItemは belongs_to :order になっているので、order_idなしにsave出来ないはずです。
もしかしてこのlogを取った時は載せているプログラムとは違ってる?

追記2
>①order_idが代入されるのは、17行目のsession[:order_id] = @current_cart.id です。
>loginの時に定義しておりません。
とすると current_cart は永遠に nil です。

どこかで order なり cart なり確定する必要があります。

User, Order, Cart の関係を教えてください。

追記の3
モデル間の関連やモデル名の不自然なところはコメントで指摘しています。
さて
Orderが1:多だとすると、Order_idが決まるのはいつ、どこでですか?
その設計が無いようです。

n~~~結構厄介そう
Userと1:1なCartを作り、CartBoxLunchで注文を取り、注文確定したらOrderを作る
のほうが作りやすそう。

投稿2020/01/13 00:07

編集2020/01/13 11:21
winterboum

総合スコア23329

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

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

nissyan

2020/01/13 20:36 編集

@winterboumさん Userと1:1なCartを作り、CartBoxLunchで注文を取り、注文確定したらOrderを作る のほうが作りやすそう。 ・・・そうなんですね!もう少しこの状態で問題解決を頑張らせてもらってもいいですか?もし、今日明日無理なら方向変えます。あと、コメントで指摘していただけたとこを修正させていただきました。 すみませんが二つ質問させてください。 ①Order_idを決める設計ということに対しての質問です。 Cartcontrollerのcreateでbinding.pryで値を確認してみました。 cart = current_userでは、orderインスタンスが表示され、すべてレコードの中身がすべてnillの状態でした。 これにidを入れる必要があると言うことでしょうか? ②formで値の送信しましたが、意図しない値が返ってきました。 商品一覧のindexで、formを使用して、弁当の個数をselectタグで送っています。 cartcontrollerのcreateで、binding.pryを使用してparams確認をしたところ、"cart"=>{"boxlunch_quantity"=>"1"}、 "commit"=>"カートの中に入れる", "boxlunch_id"=>"1"と表示されました。 なぜcartの中に弁当の個数がハッシュで入っているのか?の原因の見つけかたを教えていただきたいです boxlunch_id => "1"のように、値をとれないので、テーブルに保存されないのではと考えています。 文章が長くなってしまいましたが、宜しくお願いいたします。
winterboum

2020/01/14 00:23

①それ以前の問題です。どのタイミングでOrderが作られてますか? 沢山有るOrderのなかでどのOrderが current_cartを決めるのに使われますか? それがあやふや ② form_for @cartid),。。。 do |f| の中に =f.select :boxlunch_quantity, があるからです このcodeはモデル名から想像される役割と実際の役割がまるで異なるのでともすると勘違いします。そこを治すのを最初にやる方が良いです。 cart ってその中に沢山ものを入れるものですよね。 それが品物と1:1になってる。 スーパーに行ってカートを沢山ガラガラ引いて、1品種毎に1カート使ってる。というイメージになります。そういうのはしないから、そういうCartの使い方だとcodeを読むとき混乱します。 名前と役割を一致させるのって大事です。 まずそれから着手しましょう
nissyan

2020/01/14 14:50 編集

@winterboumさん アソシエーションの設計を見直しER図書き直しました。 これでもう一度これで組みなおそうと考えています。 上記にあったER図を変更しています 一度ご確認いただけたら幸いです。 二日間もご指導いただき本当に感謝しております。 そして同じ問題を抱えた人にER図でわかりやすく見ていただけたら幸いです。
winterboum

2020/01/14 23:29

だいぶすっきりしてきましたね。 二つ懸念があります。 1)Cartってどのように使うのでしょうか? 私の間隔だとOrderとCartが逆。 2)商品タイプ毎にmodelを作り、しまうidをOrderにもCartにも固定的に作ってます。  これですと a)商品タイプが増えた場合DBの作り直しから必要になる b)2種類のBoxランチの注文とかが出来ません
nissyan

2020/01/15 00:21

@winterboumさん winderboumさんのおかげで、自分でもすっきりにER図を整理できたと感じています。 1)Orderで仮注文→Cartにいれると考えでしたが、Cartに入れる→注文決定Orderの方がわかりやすそうですね! 変更します。 2)各4つの商品をまとめるテーブル(Productテーブル)を作成するやり方はどうでしょうか?
winterboum

2020/01/15 02:04

2)わたしでしたら、商品は全部一つのtableにして、商品カテゴリを示す項目を増やします。
nissyan

2020/01/15 10:51

@winterboumさん ご回答ありがとうございます。 勉強不足でした。 そうゆうやり方があるのですね! そのやり方を調べて実装してみます。 長い間お付き合い本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問