9
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RailsでECで用いられるカート機能を解説 / 実装してみた

Last updated at Posted at 2019-11-12

参考にした記事

Rails5でカート機能を作るためのロジックを作ってみた

おそらくこの記事を読みに来てくださる読者の方は上記の記事も読んでる可能性が高いのでモデルの設計は似せようと思います。

STEP.1 モデル設計


rails g model product name price:integer
rails g model cart
rails g model cart_item quantity:integer product:references cart:references

ここらへんは記事と全く一緒です。
因みに補足としてマイグレーション部分のコードをあげとくと以下のようになると思います。
CartItemのデフォルト値のところは後から追記してます。

マイグレーションの内容

class CreateProducts < ActiveRecord::Migration[6.0]
  def change
    create_table :products do |t|
      t.string :name
      t.integer :price

      t.timestamps
    end
  end
end


class CreateCarts < ActiveRecord::Migration[6.0]
  def change
    create_table :carts do |t|

      t.timestamps
    end
  end
end


class CreateCartItems < ActiveRecord::Migration[6.0]
  def change
    create_table :cart_items do |t|
      t.integer :quantity, default: 0
      t.references :product, null: false, foreign_key: true
      t.references :cart, null: false, foreign_key: true

      t.timestamps
    end
  end
end

上記の内容でマイグレートを通した後であればコンソールで軽く遊んでみたりしてデフォルト値が設定されているかとか確認しておくと良いかもですね。

スクリーンショット 2019-11-12 9.58.58.png

(因みに補足ですがCartItemの外部キーは存在しないものを指定するとrollbackするので先にCartとProductを作らないとハマります)

アソシエーションの内容


class Product < ApplicationRecord
end

class Cart < ApplicationRecord
  has_many :cart_items
end

class CartItem < ApplicationRecord
  belongs_to :product
  belongs_to :cart
end

※参考記事と一緒

因みに、もしここのアソシエーションを指定している意味が曖昧な人のために↓
このアソシエーションを追加することで以下のように親のモデルから関連する子のモデルが抽出出来たりするってことですね。

Cart.fitst.cart_items な感じで

スクリーンショット 2019-11-12 10.08.11.png

詳しくは本家の Active Record の関連付け

STEP.2 コントローラー設計

次にコントローラーですが無駄なコードは極力無くしてます。
例えばこの記事では一旦、View側まで書かないので helper_method などは記述してません。
必要に応じて設定して頂ければと思います。


# app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  def current_cart
    Cart.find(session[:cart_id])
  rescue ActiveRecord::RecordNotFound
    cart = Cart.create
    session[:cart_id] = cart.id
    cart
  end
end

個人的に find を使う場合はできるだけ例外処理で丁寧に扱うことを意識しています。


class CartsController < ApplicationController
  before_action :setup_cart_item!, only: [:add_item, :update_item, :delete_item]

  def show
    @cart_items = current_cart.cart_items
  end

  def add_item
    if @cart_item.blank?
      @cart_item = current_cart.cart_items.build(product_id: params[:product_id])
    end

    @cart_item.quantity += params[:quantity].to_i
    @cart_item.save
    redirect_to ''
  end

  def update_item
    @cart_item.update(quantity: params[:quantity].to_i)
    redirect_to ''
  end

  def delete_item
    @cart_item.destroy
    redirect_to ''
  end

  private

  def setup_cart_item!
    @cart_item = current_cart.cart_items.find_by(product_id: params[:product_id])
  end
end

setup_cart_item! 部分でインスタンス変数を使ってますがViewで引っ張ってくる予定がないのであれば普通の変数にリファクタリングして良いと思います。

またリダイレクト部分はよしなに変更していけば良いかなと

STEP.3 ルーティング設定

参考記事通り以下の部分を追加すればカート周りは大丈夫そうですね。

resource :carts, only: [:show]
post '/add_item' => 'carts#add_item'
post '/update_item' => 'carts#update_item'
delete '/delete_item' => 'carts#delete_item'
9
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?