С точки зрения транзакций гораздо лучше иметь вспомогательные записи, которые отслеживают операции, чем изменять одну запись на месте.
Например, если у вас есть система, в которой пользователи могут делать «ставки», то, разумеется, существует какой-то класс Bet, который определяет ставку между двумя людьми. Когда пользователи создают ставки, связанный список будет расти. На языке Rails это выглядит так:
class User < ActiveRecord::Base
has_many :bets
has_many :bet_pools,
:through => :bets
end
class Bet < ActiveRecord::Base
belongs_to :user
belongs_to :bet_pool
end
class BetPool < ActiveRecord::Base
has_many :bets
belongs_to :winning_bet
belongs_to :winning_user,
:class_name => 'User',
:through :winning_bet,
:source => :user
end
Сумма каждой ставки сохраняется в записи ставки, а BetPool представляет совокупные ставки, сделанные на конкретную ставку, хотя у вас может быть другой термин для такой вещи.
Победитель может быть определен путем назначения ассоциации bet_pool.winning_user, если и когда ставки сделаны.
Если вы хотите узнать «выигрышную запись» пользователя, то это так же просто, как сложить все пулы ставок, которые они выиграли, и сложить суммы.
Причина, по которой вы не хотите постоянно настраивать какое-либо свойство в пользовательской записи, заключается в том, что два независимых процесса могут захотеть изменить это значение, и вы можете получить условие гонки, если SQL не реализован должным образом. Например, пользователь может сделать ставку и выиграть ее за очень короткий период времени.
Если пользователь начал с 1000 долларов и одновременно выполняются две операции, это может произойти:
# Process A intending to add $500
user.balance = user.balance + 500
user.save
# Process B intending to deduct $100
user.balance = user.balance - 100
user.save
Выполнено последовательно, можно ожидать, что баланс изменится с 1000 до 1500, а затем - до 1400, но второй процесс начался с исходного значения 1000, когда он был загружен, затем настроен на 900 и сохранен, перезаписав результат первого.
Существуют такие методы, как увеличение и уменьшение для ActiveRecord, которые могут помочь с подобными вещами, но наилучшие результаты достигаются простым табулированием по мере необходимости.