Rails update_column из seed.rb

У меня есть начальный файл, который генерирует многочисленные объекты, в том числе счета и транзакции по счетам. После создания учетных записей цикл генерирует 80 транзакций для каждой учетной записи (имеется 150 учетных записей).

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

от seed.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

Попытка обновления с последней строки до "заканчивается". Я пробовал update, update_attribute, а также просто "=". Ничто не похоже на работу. Поле "остаток" счета ДОЛЖНО обновляться после каждой транзакции, чтобы обеспечить точную основу для расчета на следующей итерации цикла создания транзакции счета.

Любые предложения будут рассмотрены. Это не может быть так сложно. Опять же, все это будет работать очень хорошо, если баланс будет обновляться, как и должно.

Rails 4.1.8 / Ruby 2.1.5

Пожалуйста, помогите.. СПАСИБО!

РЕДАКТИРОВАТЬ 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

снимок экрана (неправильных) результатов

просмотр транзакций

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

методы в acct_transactions_controller, которые фактически работают для выполнения этих обновлений, когда приложение работает. Попытка повторить эту функциональность при создании вложенных семян:

  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

Обратите внимание, что вышеуказанные методы рассчитываются по-разному в зависимости от типа транзакции (+ или -) - пользователь всегда предоставляет положительное значение. Работает хоть.

Как воспроизвести такую ​​функциональность в вышеуказанном начальном файле?

Спасибо

2 ответа

Решение

Чтобы сделать эту работу, мне пришлось сделать 2 вещи:

  1. Измените синтаксис метода обновления (последняя строка seed.rb) следующим образом: account.update(balance: transaction.adjusted_bal)
  2. Добавить! (взрыв) к методу создания (AcctTransaction.create! do |transaction|)

Метод create, вероятно, прекрасно работает без взрыва, но я оставляю его, потому что теперь все работает отлично. Кроме того, я не уверен, почему использование обновления работает только с этим синтаксисом. Я пробовал другие варианты и другие методы, чтобы обновить этот столбец, но ни один из них не работал. Почти кажется, что seed.rb работает только с "голыми" методами Rails. Спасибо Deeno и всем остальным, кто помог мне с этим разобраться.

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

Если это не так, я бы просто пропустил обновление баланса после каждой транзакции и вычислял баланс в конце цикла создания транзакции.

В псевдо:

accounts.each do |account|
  80.times do
    # create transactions
  end

  account.reload
  account.balance = account.transactions.sum(:adjusted_bal)
  account.save
end

Или даже быстрее, создайте и кэшируйте баланс локально во время создания транзакции:

accounts.each do |account|
  balance = 0
  80.times do
    # create transaction
    balance += transaction.amount
  end
  account.balance = balance
  account.save
end
Другие вопросы по тегам