是否可以验证Ruby中分配给PROC的方法的数量?
-
29-09-2019 - |
题
我目前正在研究与会计有关的DSL。我想做的是:
accountant do
credit @account_1, -@amount
debit @account_2, @amount
end
当前,这执行以下方法:
class Accountant
def accountant &block
AccountantHelper.class_eval(&block)
end
end
...反过来又执行了帐户类上的块,分别称为“信用”和“借记”方法:
class AccountantHelper
def self.credit account, amount
account.credit amount
end
def self.debit account, amount
account.debit amount
end
end
(请放下有关使用class_eval()的任何火灾 - 毕竟这只是一个原型!)
目的是使该块充当交易,确保如果整个块无法成功执行,那么都不应。但是,除此之外,它还应该验证传递到块的数据的完整性。在这种情况下,我需要验证该块内是否有“信用”和“借记”方法(在双输入会计中,对于每个信用,也必须至少有一个借方,反之亦然)。目前我可以致电:
accountant do
credit @account_1, @amount
end
...并且代码将执行没有任何错误。这将是一件坏事,因为没有相应的“借记”可以使帐户保持平衡。
是否可以验证什么传递到块中?还是我在这里走错了路?
解决方案
我想你可以做你的 credit
和 debit
操作“懒惰”,以便在验证后通过包装法执行它们。这是类似于您的概念的证明,但没有跨编程的部分,而是跳过了,为了清楚起见:
def transaction
yield
if @actions.map(&:last).inject(&:+) == 0
@actions.each do |account, amount|
@accounts[account] += amount
end
@actions = []
puts 'transaction executed ok'
else
puts 'balance not zero, rolling back transaction'
# rollback (effectively, do nothing)
end
end
def credit account, amount
@actions << [account, amount]
end
def debit account, amount
@actions<< [account, -amount]
end
@actions = []
@accounts = {a: 0, b: 0, c: 0} # start with three blank accounts
transaction do
credit :a, 5
debit :b, 2
debit :c, 3
end
#=>transaction executed ok
p @accounts
#=>{:a=>5, :b=>-2, :c=>-3}
transaction do
credit :a, 5
debit :b, 4
end
#=> balance not zero, rolling back transaction
p @accounts
#=> {:a=>5, :b=>-2, :c=>-3}
不隶属于 StackOverflow