前提・実現したいこと
Railsでカート機能を備えたECサイトを作成しています。
ユーザーがログイン済みの状態でproducts(商品一覧)ページの「カートに入れる」ボタンを押すと、ユーザーidと紐づいたカートが生成され、cart_itemテーブルに商品の個数と、選んだ商品のidを保存できるようにしたいです。
現在、「カートに入れる」ボタンを押すと、下記のエラーが発生します。
cartscontrollerのsetup_cart_item!のメソッドの書き方に問題があるのか、と疑ってみたものの、
解決の糸口が見つからず、困っています。
発生している問題・エラーメッセージ
該当のソースコード
Ruby
1#routes.rb 2Rails.application.routes.draw do 3 devise_for :accounts 4 5 resources :products 6 7 resources :carts, only: [:show] 8 9 root to: 'top#index' 10 11 post '/show' ,to: 'carts#show' 12 post '/buy' ,to: 'carts#buy' 13 14 get '/my_cart' => 'carts#my_cart' 15 post '/add_item' => 'carts#add_item' 16 post '/update_item' => 'carts#update_item' 17 delete '/delete_item' => 'carts#delete_item' 18 19 get 'products/index' 20 get 'products', to: 'products#index' 21 22 get 'products/add' 23 post 'products/add' 24 25 get 'products/:id', to:'products#show' 26 27 get 'products/edit/:id', to:'products#edit' 28 patch 'products/:id/edit', to:'products#edit' 29 30 get 'products/delete/:id', to:'products#delete' 31 32 # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html 33 get 'top/index' 34 get 'top', to: 'top#index' 35 post 'top/index' 36 post 'top', to: 'top#index' 37 38 get 'top/products' 39 post 'top/products' 40 41end 42
Ruby
1#CartsController.rb 2class CartsController < ApplicationController 3 layout 'carts' 4 before_action :setup_cart_item!, only: [:add_item, :update_item, :delete_item] 5 #before_action :setup_cart_item!, only: %i[add_item update_item delete_item] 6 7 def show 8 @cart_items = current_cart.cart_items 9 #@cart_items = CartItem.all 10 end 11 12 # カート内アイテムの表示 13 def my_cart 14 @cart_items = current_cart.cart_items.find_by(product_id: params[:product_id]) 15 @total = @cart_items.inject(0) { |sum, item| sum + item.sum_of_price } 16 end 17 18 # 商品一覧画面から、「商品購入」を押した時のアクション 19 def add_item 20 @cart_item ||= current_cart.cart_items.build(product_id: params[:product_id]) 21 @cart_item.quantity += params[:quantity].to_i 22 if @cart_item.save 23 flash[:notice] = '商品が追加されました。' 24 redirect_to my_cart_path 25 else 26 flash[:alert] = '商品の追加に失敗しました。' 27 redirect_to product_url(params[:product_id]) 28 end 29 end 30 31 # カート詳細画面から、「更新」を押した時のアクション 32 def update_item 33 @cart_item.update(quantity: params[:quantity].to_i) 34 redirect_to current_cart 35 end 36 37 # カート詳細画面から、「削除」を押した時のアクション 38 def delete_item 39 @cart_item.destroy 40 redirect_to current_cart 41 end 42 43 # カート詳細画面から、「購入手続きへ」を押した時のアクション 44 def buy 45 @msg = '購入手続き' 46 end 47 48 private 49 50 def setup_cart_item! 51 @cart_item = current_cart.cart_items.find_by(product_id: params[:product_id]) 52 Rails.logger.debug("デバッグcurrent_cart2" + @current_cart.inspect) 53 end 54 55 end
Ruby
1#carts_helper.rb 2module CartsHelper 3 def current_cart 4 if current_account 5 # ユーザーとカートの紐付け 6 if Cart.where(account_id: current_account.id) 7 @current_cart = Cart.where(account_id: current_account.id) 8 else 9 @current_cart = Cart.new 10 @current_cart.account_id = current_account.id 11 @current_cart.save 12 end 13 14 logger.debug("デバッグcurrent_account" + @current_account.inspect) 15 logger.debug("デバッグcurrent_cart" + @current_cart.inspect) 16 else 17 # セッションとカートの紐付け 18 current_cart = Cart.find_by(id: session[:cart_id]) || Cart.create 19 session[:cart_id] ||= current_cart.id 20 end 21 current_cart 22 end 23 24 end
Ruby
1#ApplicationController.rb 2class ApplicationController < ActionController::Base 3 protect_from_forgery with: :exception 4 include CartsHelper 5 6end 7
HTML
1#app/views/top/products.html.erb 2<table class="table"> 3 <tr> 4 <%# <th>ID</th> %> 5 <th>商品名</th><th>価格</th><th>購入数</th><th colspan="2"></th> 6 </tr> 7 <% @products.each do |obj| %> 8 <tr> 9 <%# <td><%= obj.id %></td> 10 <td><%= obj.brand %></a></td> 11 <td><%= obj.price %></td> 12 <td><%= number_field_tag("quantity","1",min:1,max:1000,class:"form-control") %></td> 13 <td><%= button_to 'カートに入れる', controller: :carts, action: :add_item, 14 params: {cart_id: :cart_id, product_id: :product_id, quantity: :quantity } , class: 'fbtn' %></td> 15 </tr> 16 <% end %> 17</table>
Ruby
1#account.rb 2class Account < ApplicationRecord 3 # Include default devise modules. Others available are: 4 # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable 5 devise :database_authenticatable, :registerable, 6 :recoverable, :rememberable, :validatable 7 has_one :cart 8end
Ruby
1#cart_item.rb 2class CartItem < ApplicationRecord 3 belongs_to :product 4 belongs_to :cart 5 6 # カート内の商品合計に利用 7 def sum_of_price 8 product.price * quantity 9 end 10 11end 12
Ruby
1#cart.rb 2class Cart < ApplicationRecord 3 has_many :cart_items 4 belongs_to :accounts 5end 6
試したこと
current_cartがnilになっていることを疑い、デバッグしたところ、
Carts_helperのcurrent_cartでは、current_cartの値が取得できていた。
CartsContllolerのsetup_cart_item!のメソッドで、エラーが発生してしまう。
補足情報(FW/ツールのバージョンなど)
ruby 2.7.4p191
Rails 6.1.4.1
参考にしたサイト
Rails5でカート機能を作るためのロジックを作ってみた
RailsでECサイトのカート機能を実装する(ユーザーログインあり・なし両方対応)
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。