Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module ContextAccessor
- def context
- Thread.current[:context]
- end
- def context=(ctx)
- Thread.current[:context] = ctx
- end
- def execute_in_context
- original_context = self.context
- self.context = self
- yield
- self.context = original_context
- end
- end
- class Account
- attr_reader :account_id, :balance
- def self.find(id)
- (@@accounts ||= {})[id] ||= new(id)
- end
- def initialize(account_id)
- @account_id = account_id
- @balance = 1000
- end
- def update_log(message, time, amount)
- puts "#{@account_id} :: #{time.strftime('%e %b %Y %H:%M:%S%p')} : #{message} #{balance}"
- end
- end
- module MoneySource
- def decrease_balance(amount)
- @balance -= amount
- end
- end
- module MoneySink
- def increase_balance(amount)
- @balance += amount
- end
- end
- module TransferMoneySource
- include MoneySource, ContextAccessor
- def transfer_out
- raise "Insufficient funds" if balance < context.amount
- self.decrease_balance context.amount
- self.update_log "-#{context.amount}", Time.now, context.amount
- end
- end
- module TransferMoneySink
- include MoneySink, ContextAccessor
- def transfer_in
- self.increase_balance context.amount
- self.update_log "+#{context.amount}", Time.now, context.amount
- end
- end
- class TransferMoneyContext
- attr_reader :source_account, :destination_account, :amount
- include ContextAccessor
- def self.execute(amt, source_account_id, destination_account_id)
- TransferMoneyContext.new(amt, source_account_id, destination_account_id).execute
- end
- def initialize(amt, source_account_id, destination_account_id)
- @source_account = Account.find(source_account_id)
- @source_account.extend TransferMoneySource
- @destination_account = Account.find(destination_account_id)
- @destination_account.extend TransferMoneySink
- @amount = amt
- end
- def execute
- execute_in_context do
- begin
- source_account.transfer_out
- destination_account.transfer_in
- end
- end
- end
- end
- TransferMoneyContext.execute(500, :savings, :checking)
- TransferMoneyContext.execute(100, :savings, :checking)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement