确保Rails应用程序中用户“平衡”的完整性

时间:2011-02-23 07:49:49

标签: ruby-on-rails database-design transactions marketplace balance

'余额'表示信用总额与借方总和之间的差额。以下简化模式表示一个示例:

Schema http://dl.dropbox.com/u/10177092/Personal/stackoverflow_question.png

请注意“余额”列。我已经确定了三种确定平衡的方法:

(1)更新信用卡或借记卡表(并更新余额)时,请将代码包装在Transaction block中。例如:

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)创建database view

我很感激有关的建议:

  • 每种方法的优点和缺点。
  • 替代方法。

在我看来,计算余额(例如2.和3.)最能确保价值的完整性。但是,我担心(2)当用户参与额外交易时可能会变得低效。数据库视图似乎是一个理论上合理的选项,但我不相信rails_sql_views支持Rails 3,我注意到有几个线程暗示数据库视图是不受欢迎的/通常与遗留数据库相关联。

1 个答案:

答案 0 :(得分:3)

创建移动模型。

user_id, quantity, balance, updated_at, created_at

用户模型中定义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

移动模型中使用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

通过这种方式,您可以确保在添加信用卡或借记卡时,余额会更新,因为它包含在同一信用卡/借记卡移动对象中。