#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 — это онлайн-справочник, поэтому мы не пишем так, как если бы это был дискуссионный форум. Дружелюбие и некоторое знакомство — это нормально, но все же придерживайтесь сути.