前提
新規登録/ログイン機能はdeviseを使用しています。
###実現したいこと
カート機能で、ユーザーに紐づいたカートidを取得したいです。
発生している問題・エラーメッセージ
上記画像のように、ユーザーに紐づいているカートidを取得できません。
登場モデル
ユーザー: User
カート: Cart
カート内商品: CartItem
商品: Product
該当のソースコード
####モデル
User
1class User < ApplicationRecord 2 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 8 has_one :cart, dependent: :destroy 9 accepts_nested_attributes_for :cart 10 11end
Cart
1class Cart < ApplicationRecord 2 3 belongs_to :user 4 has_many :products, through: :cart_items 5 6end
CartItem
1class CartItem < ApplicationRecord 2 3 belongs_to :product 4 belongs_to :cart 5 6end
Product
1class Product < ApplicationRecord 2 3 has_many :carts, through: :cart_items 4 5end
####コントローラー
ApplicationController
1class ApplicationController < ActionController::Base 2 before_action :configure_permitted_parameters, if: :devise_controller? 3 protect_from_forgery with: :exception 4 5 helper_method :current_cart 6 7 def current_cart 8 user = User.find_by(id: current_user.id) 9 session[:cart_id] = user.cart.id 10 if session[:cart_id] 11 cart = Cart.find(session[:cart_id]) 12 else 13 cart = Cart.create 14 end 15 end 16 17 protected 18 19 def configure_permitted_parameters 20 devise_parameter_sanitizer.permit(:sign_up, keys: [cart_attributes: [:id]]) 21 end 22end
CartsController
1class CartsController < ApplicationController 2 3 def show 4 @cart_items = current_cart.cart_items 5 end 6 7 def add_item 8 @cart_item = current_cart.cart_items.build(product_id: params[:product_id]) if @cart_item.blank? 9 if @cart_item.save 10 redirect_to current_cart 11 else 12 redirect_to controller: "products", action: "show" 13 end 14 end 15 16end
####ビュー
ProductShow
1<h1>商品詳細</h1> 2 3商品名:<%= @product.name %><br> 4商品説明文:<%= @product.description %><br> 5 6<%= button_to "カートに入れる", add_item_path(product_id: @product.id) %>
#####新規登録時にcart.idも一緒に登録されるようにしています。
#####devise/user/registration_controller.rb
DeviseUserRegistration
1# frozen_string_literal: true 2 3class Users::RegistrationsController < Devise::RegistrationsController 4 # before_action :configure_sign_up_params, only: [:create] 5 # before_action :configure_account_update_params, only: [:update] 6 7 # GET /resource/sign_up 8 def new 9 @user = User.new 10 @cart = @user.build_cart 11 end 12 13 # POST /resource 14 # def create 15 # super 16 # end 17 18 # GET /resource/edit 19 # def edit 20 # super 21 # end 22 23 # PUT /resource 24 # def update 25 # super 26 # end 27 28 # DELETE /resource 29 # def destroy 30 # super 31 # end 32 33 # GET /resource/cancel 34 # Forces the session data which is usually expired after sign 35 # in to be expired now. This is useful if the user wants to 36 # cancel oauth signing in/up in the middle of the process, 37 # removing all OAuth session data. 38 # def cancel 39 # super 40 # end 41 42 # protected 43 44 # If you have extra params to permit, append them to the sanitizer. 45 # def configure_sign_up_params 46 # devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute]) 47 # end 48 49 # If you have extra params to permit, append them to the sanitizer. 50 # def configure_account_update_params 51 # devise_parameter_sanitizer.permit(:account_update, keys: [:attribute]) 52 # end 53 54 # The path used after sign up. 55 # def after_sign_up_path_for(resource) 56 # super(resource) 57 # end 58 59 # The path used after sign up for inactive accounts. 60 # def after_inactive_sign_up_path_for(resource) 61 # super(resource) 62 # end 63end
####users/sign_up
DeviseRegistration
1<h2>Sign up</h2> 2 3<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> 4 <%= render "devise/shared/error_messages", resource: resource %> 5 6 <%= f.fields_for :cart do |f| %> 7 <div class="field"> 8 <%= f.hidden_field :id, value: @cart.id %> 9 </div> 10 <% end %> 11 12 <div class="actions"> 13 <%= f.submit "Sign up" %> 14 </div> 15<% end %> 16 17<%= render "devise/shared/links" %>
####ルーティング
routes
1Rails.application.routes.draw do 2 3 devise_for :users, controllers: { registrations: 'users/registrations' } 4 resources :users 5 resources :carts, only: [:show] 6 post '/add_item' => 'carts#add_item' 7 8end
試したこと
helper_method :current_cart def current_cart user = User.find_by(id: current_user.id) # ログインユーザーのid session[:cart_id] = user.cart.id # ログインユーザーに紐づいているカートのidをセッションに保存 if session[:cart_id] cart = Cart.find(session[:cart_id]) else cart = Cart.create end end
@cart_item = current_cart.cart_items.build(product_id: params[:product_id]) if @cart_item.blank?
で、ログインユーザーに紐づいているカートオブジェクトをひっぱってきて、カート追加した時に商品追加される
というイメージなのですが、エラーが発生します。
セッションにカートidを保存したのは、そのままひっぱってくると、数値になってしまいオブジェクトが持ってこれなかったためです。
おそらく、解釈の違いが発生していると思いますが、
いくつか参考にさせて頂いてもうまく行かないので、ご教授いただけると幸いです。
補足情報(FW/ツールのバージョンなど)
ruby: 2.5.8
rails: 5.2.4
参考にさせて頂いた記事
【Rails5でカート機能を作るためのロジックを作ってみた】
・https://qiita.com/Coolucky/items/89ce3a0f25c9dfdb38c1
【deviseのフォームで2つのモデルに同時に値を送る方法(例: UserモデルとProfileモデル)】
・https://qiita.com/wonder_meet/items/9238d9bedea542ab975b
【ECサイトのカート機能】
・https://qiita.com/kenzo-ta/items/b45994c5f3fdd87b6c50
###追記(2020/12/07)
users/registrations_controller.rb
def create super @user = User.new(configure_sign_up_params) @cart = @user.build_cart @cart.save @user.save end
これを追加すると、rails cで確認した時に、Cartにuser_idが入っているのですが、
Product/show.erb
<h1>商品詳細</h1> 商品名:<%= @product.name %><br> 商品説明文:<%= @product.description %><br> <%= button_to "カートに入れる", add_item_path(product_id: @product.id) %>
商品詳細のカートに入れるを押したあと、Carts#additemにて、user.cartを取得する方法がわかりません。
class CartsController < ApplicationController def show @cart = Cart.find(params[:id]) end def add_item @user = current_user @cart = @user.cart.id @cart_item = @cart.cart_items.build(product_id: params[:product_id]) if @cart_item.blank? @cart_item.save redirect_to cart_path end end
上記のように記載するとundefined method cart_items for 2:Integer
という表示が出てしまいます。
おそらく、@user.cart.idがただの整数値だからひっぱってこれていないのかと思っています
ご教授いただけますと幸いです。
###関連付け
user.rb
has_one :cart, dependent: :destroy accepts_nested_attributes_for :cart
cart.rb
class Cart < ApplicationRecord belongs_to :user has_many :products, through: :cart_items end
product.rb
has_many :carts, through: :cart_items
12/21追記
以下のように変更したら、とりあえずカートページに商品を追加することができました。
####cart.rb
belongs_to :user has_many :cart_items
####cart_item.rb
belongs_to :product belongs_to :cart
####product.rb
has_many :cart_items
####cart_controller.rb
def index @cart = current_user.cart @cart_items = @cart.cart_items end def add_item @cart = current_user.cart @cart_item = @cart.cart_items.build(product_id: params[:product_id]) @cart_item.save redirect_to carts_path end
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/12/07 10:45
2020/12/07 11:23
2020/12/07 13:32
2020/12/07 22:40
2020/12/09 05:09