Ruby webscript, сохраняющий значения между вызовами

#ruby-on-rails #ruby #singleton #activeadmin

#ruby-on-rails #ruby #синглтон #activeadmin

Вопрос:

У меня есть эта большая проблема на ruby:

 class Finances

  @@sum = 0

  def self.add(amount)
    @@sum  = amount
  end

  def self.total
    @@sum
  end

end
  

по сути, накопитель.
Проблема в том, что он работает в первый раз, но сохраняет значения каждый раз, когда я обновляю страницу, использующую этот скрипт. (Rails activeadmin)

 ActiveAdmin.register Order, as: 'FinanceOrders' do
  idx = 0

  index do |x|
    column :id do
      idx  = 1
    end
    column :contractor do |order|
      amount = order.contractor_payment_amount
      Finances.add amount
      amount.to_money
    end

    summary = Finances.get_summary collection

    tfoot do
      tr do
            column :contractor do |order|
              Finances.total.to_money
            end
            column :profit do |order|
              (order.sum_cost / 100).to_money * (1 - FEE) - Finances.total.to_money
            end
          end
        end
        td
      end
    end

  end

end
  

Я полагаю, это какое-то кэширование классов в Rails. Вопрос в том, поскольку существует кэширование, как я могу выполнить то, что мне нужно? (Обратите внимание, что даже idx, ids = 1 не работает. Он отлично работает в первый раз, но накапливает значение idx при каждом обновлении страницы)

Ответ №1:

Во-первых, в режиме разработки все классы и модули выгружаются и загружаются при изменении содержащего файла, поэтому ваша переменная класса сбрасывается на 0 каждый раз, когда Rails перезагружает ваш класс.

Кроме того, вы должны иметь в виду, что вы работаете в многопоточной или многопроцессорной среде, в зависимости от вашего веб-сервера. Возможно, вы также работаете в среде с несколькими хостами, поэтому вам приходится делиться своим состоянием между несколькими потоками или процессами.

Переменные класса или переменные экземпляра класса могут достичь этого для многопроцессорных сред (когда вы игнорируете условия гонки), но это не работает для многопроцессорных или многохостовых сред.

С Rails у вас есть несколько способов разделить состояние между вашими запросами, например, session , база данных, файловая система и так далее.

Ответ №2:

Я инициализировал счетчик и накопитель в определении модуля / класса, а не в коде, который фактически выполнялся во время выполнения.

Решение было таким:

 index do |x|
    Finances.start
    idx = 0
  

Я создал Finances.start метод, который инициализирует @@sum , и переместил вызов в блок index do вместе со idx счетчиком, поэтому эти значения фактически инициализировались при каждом выполнении кода index do.

Это работает как шарм.

Комментарии:

1. У вас все еще есть проблемы с параллелизмом. Запустите unicorn с 5 серверами и используйте несколько запросов, тогда вы поймете, что я имею в виду. На данный момент все ваши запросы сериализуются. Вы поймете, что я имею в виду, только при использовании многопроцессорного или многопроцессорного сервера и большой нагрузки.

2. Вы предполагаете, что это будет принятый ответ? Если это так, подождите, пока время ожидания системы истечет и позволит вам выбрать его. Если это не так, пожалуйста, не добавляйте информацию о состоянии в качестве ответа. Также нежелательно иметь «спасибо» в ответе. SO — это онлайн-справочник, поэтому мы не пишем так, как если бы это был дискуссионный форум. Дружелюбие и некоторое знакомство — это нормально, но все же придерживайтесь сути.