Skip to content

Instantly share code, notes, and snippets.

@vsavkin
Created May 31, 2012 00:37
Show Gist options
  • Save vsavkin/2839869 to your computer and use it in GitHub Desktop.
Save vsavkin/2839869 to your computer and use it in GitHub Desktop.
DCI in Ruby (No Role Injection)
# Framework
# ===========================================
module ContextAccessor
def context
Thread.current[:context]
end
end
module Context
include ContextAccessor
attr_reader :role_player
def context=(ctx)
Thread.current[:context] = ctx
end
def in_context
old_context = self.context
self.context = self
return_object = yield
self.context = old_context
return_object
end
def roles map
@role_player = map
end
end
module Role
include ContextAccessor
extend self
def included clazz
clazz.extend clazz
end
protected
def player
raise "No active context" unless context
res = context.role_player[self]
raise "No object playing the role #{self}" unless res
res
end
def method_missing(method, *args, &block)
player.send(method, *args, &block)
end
end
# Data
# ===========================================
class Account
attr_reader :balance
def initialize balance
@balance = balance
end
@accounts = {1 => Account.new(100), 2 => Account.new(200)}
def self.find id
@accounts[id]
end
def increase_balance amount
@balance += amount
end
def decrease_balance amount
@balance -= amount
end
def save!
end
end
# Context
# ===========================================
class MoneyTransfer2
include Context
def self.transfer source_account_id, dest_account_id, amount
source = Account.find(source_account_id)
dest = Account.find(dest_account_id)
MoneyTransfer2.new(source, dest).transfer_amount(amount)
end
def initialize source, destination
roles SourceAccount => source,
DestinationAccount => destination
end
def transfer_amount amount
in_context do
SourceAccount.transfer amount
save_objects
end
end
def save_objects
SourceAccount.save!
DestinationAccount.save!
end
module SourceAccount
include Role
def transfer amount
DestinationAccount.deposit amount
SourceAccount.withdraw amount
end
def withdraw amount
decrease_balance amount
end
end
module DestinationAccount
include Role
def deposit amount
increase_balance amount
end
end
end
#MoneyTransfer2.transfer 1, 2, 50
#p Account.find(1).balance
#p Account.find(2).balance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment