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

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

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

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

Ruby on Rails

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

Q&A

解決済

1回答

2926閲覧

注文した商品の一覧を表示させたいです。rails

toshiki.0707

総合スコア1

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2021/07/15 03:16

前提・実現したいこと

前提
現在、Ruby on Railsを学習しており、レストランでの注文アプリを作成したいと考えています。
仕様としては
1.レストランに入って、席に置いてあるQRコードを読み取るとメニュー画面が表示される
2.メニュー一覧の商品をクリックすると、商品詳細画面に飛ぶ
3.商品詳細画面で、数量を入力して注文ボタンを押すと、カートに情報がとぶ
4.カートはsessionを用いてidを保存して、メニュー画面に戻っても、同じカートが表示される
5.カート内の商品一覧画面で注文を確定するボタンを押すとカートidが注文確定テーブルに保存され、sessionのカートidを削除する
6.席ごとに注文を判別できるように確定した注文と席の情報を結びつける
と考えております。

テーブルとしては、
1.商品を登録・表示させるためもの(Menuテーブル) 
2.注文したいものを入れるカートの役割をするためもの(Orderテーブル)
3.どの商品が何個入っているか判別するための1と2の中間テーブル(MenuOrderテーブル)
4.注文確定テーブル(OrderConfirmテーブル)
5.席番号のテーブル(Tableテーブル)
を作っています

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

注文確定された商品を出力するためにテーブルコントローラーで下記を定義しましたが
def show
@table = Table.find(params[:id])
@menu_orders = MenuOrder.where(order_id: @table.order_confirms.order_id)
end
をで定義しましたが、下記のエラーがでます。
NoMethodError in TablesController#show
undefined method `order_id' for #OrderConfirm::ActiveRecord_Associations_CollectionProxy:0x00007fa345f5e3e0 Did you mean? order

どこか記述が間違っているのでしょうか。また、エラーを解消してもこの記述では出力できない等はありますでしょうか。

該当のソースコード

ルーティング

ruby

1Rails.application.routes.draw do 2 root 'menus#index' 3 resources :tables, only: [:index, :new, :create, :show] do 4 resources :menus 5 resources :orders, only: [:new, :create] 6 get '/my_order' => 'orders#my_order' 7 post '/add_menu' => 'orders#add_menu' 8 post '/update_menu' => 'orders#update_menu' 9 delete '/delete_menu' => 'orders#delete_menu' 10 resources :order_confirms, only: [:create, :destroy] 11 end 12end

モデル周り

ruby

1class Table < ApplicationRecord 2 has_many :order_confirms 3end 4

ruby

1class Order < ApplicationRecord 2 has_many :menu_orders, dependent: :destroy 3 has_many :menus, through: :menu_orders 4 has_one :order_confirm 5end 6

ruby

1class OrderConfirm < ApplicationRecord 2 belongs_to :order 3 belongs_to :table 4end

ruby

1class Menu < ApplicationRecord 2 has_one_attached :image 3 has_many :menu_orders, dependent: :destroy 4 validates :price, numericality: { only_integer: true } 5 validates :name, presence: true 6 has_many :order, through: :menu_orders 7end

ruby

1class MenuOrder < ApplicationRecord 2 belongs_to :menu 3 belongs_to :order 4 5 def sum_of_price 6 menu.price * quantity 7 end 8end

コントローラー周り

ruby

1class TablesController < ApplicationController 2 def index 3 @tables = Table.includes(:order_confirms) 4 5 end 6 def new 7 @table = Table.new 8 end 9 def create 10 @table = Table.new(table_params) 11 if @table.save 12 redirect_to tables_path 13 else 14 render :new 15 end 16 end 17 def show 18 @table = Table.find(params[:id]) 19 @menu_orders = MenuOrder.where(order_id: @table.order_confirms.order_id) 20 end 21 22 private 23 24 def table_params 25 params.require(:table).permit(:table_num) 26 end 27 28end

ruby

1class OrdersController < ApplicationController 2 before_action :setup_order_menu!, only: [:add_menu, :update_menu, :delete_menu] 3 4 def my_order 5 @menu_orders = current_order.menu_orders.includes([:menu]) 6 @total = @menu_orders.inject(0){ |sum, item| sum + item.sum_of_price } 7 @order_confirm = OrderConfirm.new 8 end 9 10 # 商品一覧画面から、「商品購入」を押した時のアクション 11 def add_menu 12 @menu_order ||= MenuOrder.new(order_id: current_order.id, menu_id: params[:menu_id]) 13 @menu_order.quantity += params[:quantity].to_i 14 if @menu_order.save 15 flash[:notice] = '注文を追加しました' 16 redirect_to table_my_order_path(params[:table_id]) 17 else 18 flash[:alert] = '注文の追加に失敗しました' 19 redirect_to table_menu_url(table_id: params[:table_id], id: params[:menu_id]) 20 end 21 end 22 23 # カート詳細画面から、「更新」を押した時のアクション 24 def update_menu 25 @menu_order.update(quantity: params[:quantity].to_i) 26 redirect_to table_my_order_path(params[:table_id]) 27 end 28 29 # カート詳細画面から、「削除」を押した時のアクション 30 def delete_menu 31 @menu_order.destroy 32 redirect_to table_my_order_path(params[:table_id]) 33 end 34 35 private 36 37 def setup_order_menu! 38 @menu_order = current_order.menu_orders.find_by(menu_id: params[:menu_id]) 39 end 40end

ruby

1class OrderConfirmsController < ApplicationController 2 def create 3 @order_confirm = OrderConfirm.new(order_confirm_params) 4 @order = Order.find(@order_confirm.order_id) 5 if @order_confirm.save 6 session.delete(:order_id) 7 else 8 render "orders/my_order" 9 end 10 end 11 def destroy 12 13 end 14 15 private 16 17 def order_confirm_params 18 params.require(:order_confirm).permit(:order_id).merge(table_id: params[:table_id]) 19 end 20end 21

ruby

1class MenusController < ApplicationController 2 def index 3 @menus = Menu.all 4 end 5 def new 6 @menu = Menu.new 7 end 8 def create 9 @menu = Menu.new(menu_params) 10 if @menu.save 11 redirect_to root_path 12 else 13 render :new 14 end 15 end 16 def edit 17 @menu = Menu.find(params[:id]) 18 end 19 def update 20 @menu = Menu.find(params[:id]) 21 if @menu.update(menu_params) 22 redirect_to root_path 23 else 24 render :edit 25 end 26 end 27 def destroy 28 menu = Menu.find(params[:id]) 29 menu.destroy 30 end 31 def show 32 @menu = Menu.find(params[:id]) 33 @menu_order = MenuOrder.new 34 end 35 36 private 37 def menu_params 38 params.require(:menu).permit(:name, :price, :image) 39 end 40end

マイグレーション

ruby

1class CreateMenus < ActiveRecord::Migration[6.0] 2 def change 3 create_table :menus do |t| 4 t.string :name, null: false 5 t.integer :price, null: false 6 t.timestamps 7 end 8 end 9end

ruby

1# This migration comes from active_storage (originally 20170806125915) 2class CreateActiveStorageTables < ActiveRecord::Migration[5.2] 3 def change 4 create_table :active_storage_blobs do |t| 5 t.string :key, null: false 6 t.string :filename, null: false 7 t.string :content_type 8 t.text :metadata 9 t.bigint :byte_size, null: false 10 t.string :checksum, null: false 11 t.datetime :created_at, null: false 12 13 t.index [ :key ], unique: true 14 end 15 16 create_table :active_storage_attachments do |t| 17 t.string :name, null: false 18 t.references :record, null: false, polymorphic: true, index: false 19 t.references :blob, null: false 20 21 t.datetime :created_at, null: false 22 23 t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true 24 t.foreign_key :active_storage_blobs, column: :blob_id 25 end 26 end 27end 28

ruby

1class CreateOrders < ActiveRecord::Migration[6.0] 2 def change 3 create_table :orders do |t| 4 t.timestamps 5 end 6 end 7end

ruby

1class CreateMenuOrders < ActiveRecord::Migration[6.0] 2 def change 3 create_table :menu_orders do |t| 4 t.integer :quantity, default: 0 5 t.references :menu, null: false, foreign_key: true 6 t.references :order, null: false, foreign_key: true 7 t.timestamps 8 end 9 end 10end

ruby

1class CreateTables < ActiveRecord::Migration[6.0] 2 def change 3 create_table :tables do |t| 4 t.integer :table_num, null: false 5 t.timestamps 6 end 7 end 8end 9

ruby

1class CreateOrderConfirms < ActiveRecord::Migration[6.0] 2 def change 3 create_table :order_confirms do |t| 4 t.references :order, null: false, foreign_key: true 5 t.references :table, null: false, foreign_key: true 6 t.timestamps 7 end 8 end 9end

テーブルのshowビュー

ruby

1<main class="main"> 2 <div class="card__wrapper"> 3 <%= render partial: "table", locals: {table: @table} %> 4 <% @menu_orders.each do |order| %> 5 <%= order.menu.name %> 6 <% end %> 7 </div> 8 <div> 9 <%= link_to "メニュー画面へ", table_menus_path(@table.id) %> 10 </div> 11</main>

試したこと

order_confirmテーブル上にorder_idカラムがあり、データが保存されていたため、order_idがないわけではない。そのためアソシエーションに問題があるのではと考え、tableとorder_confirmのアソシエーションを見てみたが、問題は発見できなかった。

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

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

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

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

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

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

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

guest

回答1

0

ベストアンサー

model の関連にちょっと疑問はありますが、とりあえずそのままとして、
class Table < ApplicationRecord has_many :order_confirms ですと @table.order_confirms.order_id はおかしいですね。order_confirmsは配列もしくはcollentionですから order_idは持ちません。やるなら @table.order_confirms.map(&:order_id)' とか pluck(:order_id)ですね。 で、class MenuOrder はbelongs_to :order` ですから order_idは持ってるので、このエラーおかしいな。

関連にちょっと疑問

table 1:多 OrderConfirm 1:1 Order 1:多 Memue
とありますが、
OrderConfirmを挟む必要は無いのでは
挟んだとしても 1:1 なのでは

投稿2021/07/15 06:41

winterboum

総合スコア23401

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

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

toshiki.0707

2021/07/15 08:09 編集

ご回答いただきありがとうございます!! ご指摘の通りで、pluckを使ったことで無事にエラーを解消することができました! ### 関連について 関連についてですが、Orderの段階(カート機能に入れた段階)では、まだ商品の数量変更や取り消しをユーザーができるように設定しているため、レストランでの使用を考えた際に、厨房側で商品を作っていたら、数量が減った・無くなったということが起こらないように一度OrderConfirmに移して注文を確定させるという処理が必要かと考えました。 order.idをsessionに保存していますが、注文確定する段階(OrderConfirmを挟む際)でorder.idを消して、もう一度注文する際には新しいOrderを作成する形で考えています。そのため、注文の度にOrderが新しく作られるため、Tableとの関係は1対多と定義しました。長文でわかりにくくてすみません。考え方が間違っている・もっとシンプルにできる等アドバイスがありましたらいただけますと幸いです。
winterboum

2021/07/15 08:59

注文の確定はOrderにstatusをつければ済むかと思うのです
toshiki.0707

2021/07/16 01:59

Orderだけで可能なんですね!すみません勉強不足で、statusをつければ可能ということが理解できないので、カート機能についてもっと色々な記事を見てみます!もし、この記事はわかりやすくて参考になる等ありましたら、教えていただけますと幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問