Rails update_column 来自 seeds.rb

Rails update_column from within seeds.rb

我有一个生成大量 objects 的种子文件,包括 账户 账户交易 。创建账户后,一个循环为每个账户生成80笔交易(有150个账户)。

一切正常,除了我需要更新帐户的 余额 列以反映交易引起的变化。我已经尝试过 100 种不同的方法。这是我最近的方法:

来自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

正在尝试更新 "ends" 之前的最后一行。我尝试了 update、update_attribute 以及“=”。似乎没有任何效果。帐户的 "balance" 字段 必须 在每次交易后更新,以便为帐户的 next 迭代提供准确的计算基础事务创建循环。

我们会考虑任何建议。这不可能那么困难。同样,如果余额得到应有的更新,整个事情就会正常进行。

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

(错误)结果的屏幕截图

如您所见,发生的是原始余额(放大后在 header 中看到),保持不变。因此,每笔交易都是根据此金额计算的。

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

请注意,上述方法根据交易类型(+ 或 -)计算不同 - 用户始终提供正值。虽然有效。

如何在上面的种子文件中重现这种功能?

谢谢

当然,有很多方法可以做到这一点,但乍一看,您的方法似乎可行。我的第一个想法是,您在模型上有一些与您的逻辑冲突的生命周期挂钩或反缓存配置。 (您可能想向我们展示您的模型定义)

如果不是这种情况,我会在每次交易后跳过更新余额,并在交易创建循环结束时计算余额。

伪:

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

为了完成这项工作,我必须做两件事:

  1. 将更新方法的语法(seeds.rb 的最后一行)更改为:account.update(balance: transaction.adjusted_bal)
  2. 加一个! (bang) 创建方法 (AcctTransaction.create! do |transaction|)

create 方法可能在没有爆炸的情况下工作正常,但我将其保留,因为现在一切正常。另外,我不确定为什么使用 update 只适用于这种语法。我尝试了其他变体和其他方法来更新此列,none 似乎有效。几乎看起来 seeds.rb 只适用于 "bare bones" Rails 方法。感谢 Deeno 和所有帮助我解决这个问题的人。