Skip to main content

Shopping Cart Goods Count Update in Rails(class variable)

Published: November 26, 2017 Updated: May 8, 2026 Larry Qu 2 min read
Table of Contents

,(Rails),。

,,。application_controller

,,controller, ,,@@,$,controller,application_controller

,,,application_controller? ,,carts_controller、、action。 ,action,application_controller,。****, 。

,view,,@。

application_controller,,。。 keyid,value,,countis_changed

class ApplicationController < ActionController::Base
  before_action :set_cart_num

  # for cache num,
  CartCount = Struct.new(:count, :is_changed)
  # dict, {user_id => CartCount, ... }
  @@cached_cart = {}

  def set_cart_num
    if current_user
      id = current_user.id
      # exist
      if @@cached_cart[id]
        if @@cached_cart[id].is_changed
          # changed
          @cart_num = @@cached_cart[id].count = count_carts
          @@cached_cart[id].is_changed = false
        else
          # "no change"
          @cart_num = @@cached_cart[id].count
        end
      else
        # "not exist"
        @@cached_cart[id] = CartCount.new(count_carts, false)
        @cart_num = @@cached_cart[id].count
      end
    end
  end

  def count_carts
    current_user.carts.collect{|item| item.amount}.sum
  end
  # ,,。
  # cart_controllerorders_controller
  def notify_cart_change
    @@cached_cart[current_user.id].is_changed = true
  end

end

carts_controller,carts_controller,。

class CartsController < ApplicationController
  after_action :notify_cart_change, only: [:create, :update, :destroy]
end

orders_controller

class CartsController < ApplicationController
  after_action :notify_cart_change, only: [:create, :update, :destroy]
end

view

<a href="/carts"><img src="/assets/shopping-cart1.png" class="" alt="carts">
  <span class="badge"><%= @cart_num %></span>
</a>

schema of carts

create_table "carts", id: :serial, force: :cascade do |t|
  t.integer "user_id"
  t.integer "product_id"
  t.integer "amount"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["product_id"], name: "index_carts_on_product_id"
  t.index ["user_id"], name: "index_carts_on_user_id"
end

1: @@cached_cart = {},,,,,,redis。

# routes.rb
devise_for :users, controllers: {
  :passwords => 'users/passwords',
  :registrations => 'users/registrations',
  :sessions => 'users/sessions'
}
# sessions_ontroller.rb

class Users::SessionsController < Devise::SessionsController
  before_action :clear_cart_count, only: [:destroy]
  private
  # after user sign_out, delete the cached cart count.
  def clear_cart_count
    @@cached_cart.delete current_user.id
  end
end

2: ?? ,。 ,,。

require 'objspace'
CartCount = Struct.new(:count, :is_changed)
c = CartCount.new(12, false)
p ObjectSpace.memsize_of(c)
# => 40
d = [13, false]
p ObjectSpace.memsize_of(d)
# => 40

,,40。 application_controller,application_controller?。

Resources

Comments

👍 Was this article helpful?