2

「残高」は、貸方の合計と借方の合計の差を表します。次の簡略化されたスキーマは、例を表しています。

スキーマ http://dl.dropbox.com/u/10177092/Personal/stackoverflow_question.png

「残高」列に注意してください。バランスを決定するための 3 つのアプローチを特定しました。

(1) クレジット テーブルまたはデビット テーブルを更新する (および残高を更新する) 場合は、コードをTransaction ブロックでラップします。例えば:

ActiveRecord::Base.transaction do
  current_user.credits.credit(100)
  current_user.balance.increment(100)
end

(2) 「残高」列を含めないでください。代わりに、要求されるたびに残高を計算します。

credit = current_user.credits.sum('amount')
debit = current_user.debits.sum('amount')
balance = credits - debits

(3)データベース ビューを作成します。

以下に関するアドバイスをいただければ幸いです。

  • 各アプローチの長所と短所。
  • 代替アプローチ。

値の整合性を確保するには、バランス (例: 2. と 3.) を計算するのが一番だと思います。ただし、(2)ユーザーが追加のトランザクションを行うと非効率になる可能性があることを懸念しています。データベース ビューは理論的には適切な選択肢のように思えますが、rails_sql_viewsが Rails 3 をサポートしているとは思えません。また、データベース ビューが望ましくない、またはレガシー データベースに関連付けられていることを示唆するスレッドがいくつかあることに気付きました。

4

1 に答える 1

3

ムーブメントモデルを作成します。

user_id, quantity, balance, updated_at, created_at

Userモデルで add_credit、add_debit、および balance インスタンス メソッドを定義します。

 def add_credit(quantity)   
    self.movements.create :quantity => quantity 
 end

 def add_debit(quantity)
    self.movements.create :quantity => -quantity
end

def balance
  self.movements.last.balance
end

Movementモデルで after_save コールバックを使用します。

before_save :update_balance

def update_balance
    if balance
       balance = self.user.movements.last.balance + self.quantity 
    else
       balance = self.quantity # First movement
    end
end

このようにして、同じ貸方/借方移動オブジェクトに含まれているため、貸方または借方が追加されたときに残高が確実に更新されます。

于 2011-02-23T08:30:07.913 に答える