从seeds.rb中的Rails update_column

时间:2015-04-12 21:20:40

标签: ruby-on-rails ruby activerecord seeding

我有一个生成大量对象的种子文件,包括帐户帐户交易。创建帐户后,循环为每个帐户生成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

尝试使用“结束”之前的最后一行进行更新。我已经尝试了 update,update_attribute ,以及“=”。似乎没什么用。帐户的“余额”字段必须在每笔交易后更新,以便为帐户交易创建循环的 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

(错误)结果的屏幕截图

transactions view

正如您所看到的,会发生什么是原始余额(如果放大则在标题中看到),持续。因此,每笔交易都是根据这笔金额计算的。

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 个答案:

答案 0 :(得分:1)

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

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

在伪:

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 :(得分:0)

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

  1. 将update方法的语法(seeds.rb的最后一行)更改为:account.update(balance: transaction.adjusted_bal)
  2. 添加一个! (bang)到create方法(AcctTransaction.create! do |transaction|
  3. 创建方法可能在没有爆炸的情况下正常工作,但是我将其留在原因,因为现在一切都很好。此外,我不确定为什么使用更新仅适用于此语法。我尝试了其他变种和其他方法来更新此列,但似乎没有一种方法可行。几乎看起来像seeds.rb只适用于“裸骨”Rails方法。感谢Deeno和其他所有帮助我解决这个问题的人。