【问题标题】:Class Variables instantiated(refreshed) for each new instance为每个新实例实例化(刷新)的类变量
【发布时间】:2020-07-27 08:19:43
【问题描述】:

我有两个类 Categoryorder_item,其中 order_item belongs_to 一个类别。

我想将唯一的“类别”项添加到一个类变量中,该类变量是一个“类别”数组,由数组类变量 @@categoriesList 表示,每次检测到新类别时在实例变量中。

这是我尝试过的。

class OrderItemsController < ApplicationController

@@categoriesList = []

def create
    @order_item = OrderItem.new(order_item_params)
    if @order_item.save

      @total = @order_item.order.total
      @orderItemCategory = @order_item.category

      if @orderItemCategory.set?
        if !(@@categoriesList.include? @orderItemCategory)
            @total += @orderItemCategory.price
            @@categoriesList.push(@orderItemCategory)
        end
........
........
end

代码说明:

我不想考虑下一个 order_item 实例的价格,如果属于同一类别价格的上一个 order_item 的价格已经被考虑在内.

例如: Egg 和 Milk 都属于 Combo-1。所以我只想考虑一次 Combo-1 的价格,而不是每个 order_item 实例,即鸡蛋和牛奶,这会使总金额翻倍。

我尝试了什么:

在考虑价格后,我推送 order_item 的类别名称。当创建下一个 order_item 时,我通过在当前的 @@categoriesList 类变量中检查该 order_item 的类别的价格是否已被记录。

问题: 在每个实例中,当我检查类变量 @@categoriesList 时,它会返回一个空数组列表,并且不会显示以前推送到该数组的记录。

我想要一个类似于 java 中的静态变量的东西,其中类的每个实例共享同一个变量,而实际上并不为每个实例刷新变量中的数据。

【问题讨论】:

    标签: ruby-on-rails ruby class-variables


    【解决方案1】:

    您几乎不需要类变量,因为它们不是线程安全的,也不是跨请求的实际持久性,这实际上适用于几乎任何编程语言。每次重新加载代码时,类变量都会被重置。

    您可以通过正确地对域进行建模来真正完成您想要做的事情。对于结账系统,它已经完成了十亿次,常见的模式是:

    class Order < ApplicationRecord
      has_many :line_items
      has_many :products, through: :line_items
    end
    
    # rails g model line_item quantity:decimal unit_price:decimal order:belongs_to product:belongs_to
    class LineItem < ApplicationRecord
      belongs_to :order
      belongs_to :product
    end
    
    class Product < ApplicationRecord
      has_many :line_items
      has_many :orders, through: :line_items
    end
    

    在代表订单上实际行的行项目表中,您存储了该项目所属的订单、数量和购买时的单价。要对订单进行统计,请将订单项相加:

    class LineItem < ApplicationRecord
      # ...
      def net
        quantity * unit_price
      end
    end
    
    class Order < ApplicationRecord
       # ...
      def net
        line_items.sum(&:net)
      end
    end
    

    那么你可以打电话给order.net,它会给你净额。我不知道您将把这些类别放在哪里,但是如果我们通过转到产品来查看这里的价格,除非价格完全是静态的,否则我们将无法解释过去的交易。

    这是您创建订单项的方式:

    resources :orders do
      resources :line_items
    end
    
    class LineItemsController < ApplicationController
      before_action :set_order
    
      # GET /orders/1/line_items
      def new
        @line_item = @order.line_items.new
        @products = Product.all
      end
    
      # POST /orders/1/line_items
      def create
        @line_item = @order.line_items.new(line_item_params) do |items|
          items.unit_price = li.product.price # stores the price at time of purchase
        end
        if @line_item.save
          redirect_to @order
        else
          @products = Product.all
          render :new
        end
      end
    
      # ...
    
      private
    
      def line_item_params
        params.require(:line_item)
              .permit(:quantity, :product_id)
      end
    
      def set_order
        @order = Order.find(params[:order_id])
      end
    end
    
    <%= form_with(model: [@order, @line_item], local: true) do |f| %>
      <div class="field">
        <%= f.label :product_id %>
        <%= f.collection_select :product_id, @products, :id, :name %>
      </div>
      <div class="field">
        <%= f.label :quantity %>
        <%= f.number_field :quantity %>
      </div>
    
      <%= f.submit %>
    <% end %>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-05
      • 2021-05-11
      • 1970-01-01
      • 2019-07-05
      • 1970-01-01
      • 1970-01-01
      • 2021-06-18
      • 2015-04-26
      相关资源
      最近更新 更多