Ruby on rails 生产中Rails数据库中无法解释的大量购物车

Ruby on rails 生产中Rails数据库中无法解释的大量购物车,ruby-on-rails,postgresql,session,heroku,shopping-cart,Ruby On Rails,Postgresql,Session,Heroku,Shopping Cart,我使用Rails 5、postgres和heroku构建了一个电子商务应用程序,使用session对象存储购物车id的经典购物车。感谢heroku的警告,我发现数据库中购物车的数量以一种非常奇怪的方式增加。每分钟可超过50次;这并不是因为有很多客户访问该网站,目前该网站规模相当小。在其他时刻,Carts表的行数是稳定的 这是我的应用程序控制器: class ApplicationController < ActionController::Base protect_from_forg

我使用Rails 5、postgres和heroku构建了一个电子商务应用程序,使用session对象存储购物车id的经典购物车。感谢heroku的警告,我发现数据库中购物车的数量以一种非常奇怪的方式增加。每分钟可超过50次;这并不是因为有很多客户访问该网站,目前该网站规模相当小。在其他时刻,Carts表的行数是稳定的

这是我的应用程序控制器:

class ApplicationController < ActionController::Base

  protect_from_forgery with: :exception
  around_action :switch_locale

  before_action :configure_permitted_parameters, if: :devise_controller?
  before_action  :current_cart
  after_action :store_action


  def switch_locale(&action)
  locale = params[:locale] || I18n.default_locale
  I18n.with_locale(locale, &action)
  end

  def default_url_options
    { locale: I18n.locale == I18n.default_locale ? nil : I18n.locale }
  end


  def current_cart

        if session[:cart_id]
          cart = Cart.find_by_id(session[:cart_id])
          if cart == nil
            session[:cart_id] = nil
          end

          if cart.present?
            @current_cart = cart
          else
            session[:cart_id] = nil
          end
        end


        if session[:cart_id] == nil
          @current_cart = Cart.create
          session[:cart_id] = @current_cart.id
        end
  end


  def store_action
      return unless request.get?
      if (request.path != "/users/sign_in" &&
          request.path != "/users/sign_up" &&
          request.path != "/users/password/new" &&
          request.path != "/users/password/edit" &&
          request.path != "/users/confirmation" &&
          request.path != "/users/sign_out" &&
          !request.xhr?) # don't store ajax calls
        store_location_for(:user, request.fullpath)
      end
    end

  protected

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:username])
  end
class OrdersController < ApplicationController

  before_action :authenticate_user!

  def create
    @order = Order.new

    total = []
    @current_cart.order_items.each do |item|

      total << item.product.price_cents * item.quantity.to_i
    end

    @order.amount_cents_cents = total.sum

    if @order.amount_cents_cents == 0
       Cart.destroy(session[:cart_id])
       session[:cart_id] = nil
       redirect_to root_path
    else
      @current_cart.order_items.each do |item|
        @order.order_items << item
        item.cart_id = nil
      end

      @user = current_user
      @order.user_id = @user.id
      @order.save


      Cart.destroy(session[:cart_id])
      session[:cart_id] = nil

      redirect_to order_path(@order)
    end

昨天我删除了生产数据库的所有cart,今天我已经有3000多行了。这听起来很糟糕。是否有人可以帮助解决此问题?

如果我正确阅读了您的代码:

before_action  :current_cart
def current_cart
  ...
  if session[:cart_id] == nil
    @current_cart = Cart.create
    session[:cart_id] = @current_cart.id
  end
end
ApplicationController
中添加的将对继承自
ApplicationController
的每个控制器中的每个操作执行

甚至你的主页也可能执行它。当
session[:cart\u id]
为nil(根据您当前的问题,这种情况经常发生)时,每次访问都将创建一个
cart

IMO的
当前购物车
的目的与
当前购物车用户
相同,是查找购物车,而不是创建购物车。如果它不存在,那么其他动作的目的就是创造它


你应该稍微修改一下你的逻辑。祝你好运

如果我正确阅读了您的代码:

before_action  :current_cart
def current_cart
  ...
  if session[:cart_id] == nil
    @current_cart = Cart.create
    session[:cart_id] = @current_cart.id
  end
end
ApplicationController
中添加的将对继承自
ApplicationController
的每个控制器中的每个操作执行

甚至你的主页也可能执行它。当
session[:cart\u id]
为nil(根据您当前的问题,这种情况经常发生)时,每次访问都将创建一个
cart

IMO的
当前购物车
的目的与
当前购物车用户
相同,是查找购物车,而不是创建购物车。如果它不存在,那么其他动作的目的就是创造它


你应该稍微修改一下你的逻辑。祝你好运

我认为这不能通过静态代码分析来解决。也许你应该添加一些调试日志。谢谢你的回答@LaurenzAlbe,我用Heroku logsI编辑了这个问题。在几秒钟的时间间隔内,我在日志中看到了许多来自同一源的
GET”/en/carts/:id“
调用。那可能是某种蜘蛛或机器人。您可以研究使用rack攻击来阻止这类事情,但首先您应该了解GET请求创建购物车的原因,在您有东西放入购物车之前,您不应该创建购物车。我认为这不能通过静态代码分析来解决。也许你应该添加一些调试日志。谢谢你的回答@LaurenzAlbe,我用Heroku logsI编辑了这个问题。在几秒钟的时间间隔内,我在日志中看到了许多来自同一源的
GET”/en/carts/:id“
调用。那可能是某种蜘蛛或机器人。您可以研究使用rack攻击来阻止这类事情,但首先您应该了解GET请求创建购物车的原因,在您有东西放入购物车之前,您不应该创建购物车。我想您就在这里,
GET”/en/carts/:id“
可能不应该创建购物车。谢谢@razvans和mu太短了!我修改了代码,以便仅在需要时创建购物车。它还不是完美的,但是Cart.count在Heroku控制台中一个小时内是0,所以这是一种解脱!然而,你认为使用rack attack是否仍然有用,就好像该站点曾经是目标一样,它可能是其他危险的爬行器或机器人的目标?如果你有rack attack,你可能不会发现这个问题。我说你要确保所有的端点都是安全的、优化的、快速的,然后机器人是无害的。我想你就在这里,
GET”/en/carts/:id“
可能不应该创建一个购物车。谢谢@razvans和mu太短了!我修改了代码,以便仅在需要时创建购物车。它还不是完美的,但是Cart.count在Heroku控制台中一个小时内是0,所以这是一种解脱!然而,你认为使用rack attack是否仍然有用,就好像该站点曾经是目标一样,它可能是其他危险的爬行器或机器人的目标?如果你有rack attack,你可能不会发现这个问题。我说你要确保所有的端点都是安全的、优化的、快速的,然后机器人是无害的。
before_action  :current_cart
def current_cart
  ...
  if session[:cart_id] == nil
    @current_cart = Cart.create
    session[:cart_id] = @current_cart.id
  end
end