Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save rinaldifonseca/2886209 to your computer and use it in GitHub Desktop.
Save rinaldifonseca/2886209 to your computer and use it in GitHub Desktop.
DCI in Ruby (Role Injection)
# Framework
# ===========================================
module ContextAccessor
def context
Thread.current[:context]
end
end
module Context
include ContextAccessor
def context=(ctx)
Thread.current[:context] = ctx
end
def in_context
old_context = self.context
self.context = self
yield
self.context = old_context
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 MoneyTransfer
include Context
def self.transfer source_account_id, dest_account_id, amount
source = Account.find(source_account_id)
dest = Account.find(dest_account_id)
MoneyTransfer.new(source, dest).transfer_amount(amount)
end
attr_reader :source, :destination
def initialize source, destination
@source = source.extend SourceAccount
@destination = destination.extend DestinationAccount
end
def transfer_amount amount
in_context do
source.transfer_out amount
save_changes
end
end
private
def save_changes
source.save!
destination.save!
end
# Roles
# ===========================================
module SourceAccount
include ContextAccessor
def transfer_out amount
decrease_balance amount
context.destination.deposit amount
end
end
module DestinationAccount
include ContextAccessor
def deposit amount
increase_balance amount
end
end
end
MoneyTransfer.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