Search code examples
ruby-on-railsrubyactiverecordseeding

Rails update_column from within seeds.rb


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

transactions view

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


Solution

  • To make this work, I had to do 2 things:

    1. Change the syntax of update method (last line of seeds.rb) to this : account.update(balance: transaction.adjusted_bal)
    2. Add a ! (bang) to the create method (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.