确保用户“余额”的完整性;在 Rails 应用程序中

发布于 2024-10-19 07:18:12 字数 1160 浏览 2 评论 0原文

“余额”代表贷方总和与借方总和之间的差额。以下简化架构代表了一个示例:

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

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

(1) 更新贷项或借项表(并更新余额)时,将代码包装在 事务块。例如:

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,而且我我注意到有几个线程暗示数据库视图是不可取的/通常与遗留数据库相关。

'Balance' represents the difference between the sum of credits, and the sum of debits. The following simplified schema represents an example:

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

Note the 'balance' column. I have identified three approaches to determining balance:

(1) When updating the credit or debit table (and updating the balance), wrap the code in a Transaction block. For example:

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

(2) Don't include a 'balance' column - instead, calculate the balance each time it is requested:

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

(3) Create a database view.

I would appreciate advice regarding:

  • The advantages and disadvantages of each approach.
  • Alternative approaches.

It seems to me like calculating balance (e.g. 2. and 3.) best ensure the integrity of the value. However, I am concerned (2) may become inefficient as users engage in additional transactions. Database views seem like a theoretically sound option, but I don't believe rails_sql_views supports Rails 3, and I have noticed several threads that imply database views are undesirable/often associated with legacy databases.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

饮惑 2024-10-26 07:18:12

创建运动模型。

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

这样可以确保在添加贷方或借方时更新余额因为它包含在同一个贷方/借方移动对象中。

Create a Movement model.

user_id, quantity, balance, updated_at, created_at

Define add_credit, add_debit and balance instance methods in User model:

 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

Use an after_save callback in Movement model:

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

This way you assure that when credit or debit is added, the balance is updated because it's contained in the same credit/debit movement object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文