Переменные класса создаются (обновляются) для каждого нового экземпляра

У меня есть два класса Category и order_item, где order_item принадлежит категории.

Я хочу добавить уникальные элементы «категории» в переменную класса, которая представляет собой массив «категорий» и представлена ​​переменной класса массива @@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, относящегося к цене той же категории.

Например: Яйцо и Молоко относятся к Combo-1. Поэтому я просто хочу учесть цену Комбо-1 один раз, а не для каждого экземпляра order_item, т.е. яйца и молока, что удвоило бы общую сумму.

Что я пробовал:

Я нажимаю название категории order_item после того, как его цена была принята во внимание. И когда создается следующий order_item, я проверял, была ли уже записана цена этой категории order_item, проверяя ее в текущей переменной класса @@categoriesList.

Проблема: каждый раз, когда я проверяю переменную класса @@categoriesList, она возвращает пустой список массивов, и предыдущие записи, которые были помещены в этот массив, не отображаются.

Я хочу что-то вроде статической переменной в java, где каждый экземпляр класса использует одну и ту же переменную без фактического обновления данных в переменной для каждого экземпляра.


person Sheriff Hussain    schedule 14.04.2020    source источник


Ответы (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 %>
person max    schedule 14.04.2020