2010-11-28 6 views
0

私は現在、会計に関してDSLを取り組んでいます。私は何をできるようにしたいと思いますがある:呼び出し、RubyでProcに割り当てられているメソッドの数を確認できますか?

class Accountant 
    def accountant &block 
    AccountantHelper.class_eval(&block) 
    end 
end 

...今度はAccountantHelperクラス上のブロックを実行します。現在、

accountant do 
    credit @account_1, [email protected] 
    debit @account_2, @amount 
end 

、これは以下のメソッドを実行しますそれぞれ「信用」と「借方」方法:

class AccountantHelper 
    def self.credit account, amount 
    account.credit amount 
    end 

    def self.debit account, amount 
    account.debit amount 
    end 
end 

(class_evalメソッドを(使用についていかなる火を我慢してください) - これは結局唯一のプロトタイプです!)

目的は、ブロックがトランザクションとして機能するようにして、ブロック全体を正常に実行できない場合は、そのブロックのどれもが確実に実行されないようにします。ただし、これに加えて、ブロックに渡されるデータの整合性も検証する必要があります。この場合、ブロック内に「クレジット」と「デビット」の両方の方法があることを確認する必要があります(二重計算では、クレジットごとに最低1つのデビットが必要です)。

accountant do 
    credit @account_1, @amount 
end 

を...そして、コードがエラーなしで実行されます:現在、私は呼び出すことができます。これはバランスのとれた口座を維持するための対応する「デビット」がないため、悪いことです。

ブロックに何が渡されるのかを確認することはできますか?それとも、ここで間違った道を歩いていますか?

答えて

2

creditdebitアクションは、検証後にラッパーメソッドによって実行されるように「遅延」することができます。ここではあなたに似たコンセプトの証明は、ですが、メタプログラミングの一部せず、明確にするためにスキップ:

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} 
+0

おかげで、それは私が必要とするまさにそれだ:)私は当初、私は「クレジット」の両方を検証するために必要なことを考えていましたブロック内に「デビット」ステートメントが定義されていますが、金額の合計がゼロになったことを単純に検証するとは考えていませんでした。これは、一度にブロックの完全性を検証する簡単なソリューションです。 – 6twenty

関連する問題