Reputation: 823
I have a seed file that generates numerous objects, including accounts and account transactions. After the accounts are created, a loop generates 80 transactions for each account (there are 150 accounts).
Everything works well, except I need the account's balance column to be updated to reflect the change caused by the transaction. I've tried this in 100 different ways. Here is my most recent approach:
from seeds.rb
accounts.each do |account|
80.times do
type = types.sample
case (type)
when 1
description = descriptions_ATM_Withdrawal.sample
amount = (atm_amounts.sample) *-1
when 2
description = descriptions_Check.sample
amount = ((500.0 - 5.0) * rand() + 5) *-1
when 3
description = descriptions_Deposit.sample
amount = (2000.0 - 5.0) * rand() + 5
when 4
description = descriptions_AutoDraft.sample
amount = ((350.0 - 5.0) * rand() + 5) *-1
when 5
description = descriptions_POS.sample
amount = ((150.0 - 5.0) * rand() + 5) *-1
when 6
description = descriptions_Transfer
amount = (500.0 - 5.0) * rand() + 5
when 7
description = descriptions_Withdrawal
amount = ((500.0 - 5.0) * rand() + 5) *-1
when 99
description = descriptions_Miscellaneous
amount = ((500.0 - 5.0) * rand() + 5) *-1
end
AcctTransaction.create do |transaction|
transaction.id = SecureRandom.random_number(99999999999999)
transaction.account_id = account.id
transaction.transaction_type_id = type
transaction.description = description
transaction.amount = amount
transaction.adjusted_bal = account.balance + transaction.amount
# keep transaction in chronological order unless it's the first one
unless AcctTransaction.exists?(account_id: transaction.account_id)
transaction.date = rand(account.date_opened..Time.now)
else
transaction.date = rand(AcctTransaction.where(account_id: transaction.account_id).last.date..Time.now)
end
end
Account.find(AcctTransaction.last.account_id).update_column(:balance, AcctTransaction.last.adjusted_bal)
end
end
Trying to update with the last line before the "ends". I've tried update, update_attribute, as well as just "=". Nothing seems to work. The account's "balance" field MUST be updated after each transaction in order to provide an accurate basis for calculation in the next iteration of the account transaction creation loop.
Any suggestions will be considered. This can't be that difficult. Again, the whole thing would work just fine if the balance gets updated like it should.
Rails 4.1.8 / Ruby 2.1.5
Please help.. THANK YOU!
EDIT account.rb:
class Account < ActiveRecord::Base
belongs_to :customer
belongs_to :user
has_one :acct_type
has_many :acct_transactions, :dependent => :destroy
accepts_nested_attributes_for :acct_type
accepts_nested_attributes_for :acct_transactions
validates :acct_type_id, presence: true
end
acct_transaction.rb
class AcctTransaction < ActiveRecord::Base
belongs_to :account
has_one :transaction_type
accepts_nested_attributes_for :transaction_type, :allow_destroy => false
end
screen shot of (wrong) results
As you can see, what happens is the original balance (seen in header if you zoom in), persists. Every transaction, therefore, is calculated based on this amount.
methods in acct_transactions_controller that actually work to perform these updates when the app is live. Trying to replicate this functionality when creating the nested seeds:
public
def modify_acct_balance
account = Account.find(@acct_transaction.account_id)
case @acct_transaction.transaction_type_id
when 1,2,4,5,7
account.update(balance: account.balance - @acct_transaction.amount)
when 3
account.update(balance: account.balance + @acct_transaction.amount)
end
end
def adjust_balance
case @acct_transaction.transaction_type_id
when 2,4,5,7
@acct_transaction.adjusted_bal = Account.find(@acct_transaction.account_id).balance - @acct_transaction.amount
when 3
@acct_transaction.adjusted_bal = Account.find(@acct_transaction.account_id).balance + @acct_transaction.amount
end
end
Please note that the above methods calculate differently based on the transaction type (+ or -) - user always supplies positive value. Works though.
How to reproduce this kind of functionality in the above seed file?
Thanks
Upvotes: 1
Views: 645
Reputation: 823
To make this work, I had to do 2 things:
account.update(balance: transaction.adjusted_bal)
AcctTransaction.create! do |transaction|
)The create method probably works fine without the bang, but I'm leaving it in because everything works great now. Also, I'm not sure why using update only works with this syntax. I tried other variants and other methods to update this column and none seemed to work. Almost seems like seeds.rb only works with "bare bones" Rails methods. Thanks to the Deeno and all others who've helped me work this out.
Upvotes: 0
Reputation: 77348
There are many ways to do this, for sure, but at first glance it looks like your approach would work. My first thought is that the you have some life-cycle hooks or counter-cache configuration on the models that's conflicting with your logic. (You may want to show us your model definitions)
If that's not the case, I'd simply skip updating the balance after every transaction and calculate the balance at the end of the transaction-creation loop.
In pseudo:
accounts.each do |account|
80.times do
# create transactions
end
account.reload
account.balance = account.transactions.sum(:adjusted_bal)
account.save
end
Or even faster, build and cache the balance locally during transaction-creation:
accounts.each do |account|
balance = 0
80.times do
# create transaction
balance += transaction.amount
end
account.balance = balance
account.save
end
Upvotes: 1