Skip to content

Instantly share code, notes, and snippets.

@raderj89
Last active September 10, 2015 20:43
Show Gist options
  • Save raderj89/c30ac74028a3fbcd058b to your computer and use it in GitHub Desktop.
Save raderj89/c30ac74028a3fbcd058b to your computer and use it in GitHub Desktop.
DCI example
class Account < ActiveRecord::Base
def transfer_to(destination, amount)
self.balance -= amount
destination.balance += amount
destination.save
self.save
end
end
class TransfersController < ApplicationController
def transfer
@source = Account.find(params[:account_id])
@destination = Account.find(params[:destination_id])
if @source.transfer_to(@destination, params[:amount])
flash[:success] = "Transfer successful!"
redirect_to @source
else
flash[:error] = "There was a problem."
render :transfer
end
end
end
class MoneyTransfer
def initialize(source, destination)
@source = source.extend Transferrer
@destination = destination
end
def execute(amount)
@source.transfer_to(@destination, amount)
end
private
module Transferrer
def transfer_to(destination, amount)
self.balance -= amount
destination.balance += amount
destination.save
self.save
end
end
end
class TransfersController < ApplicationController
def transfer
source = Account.find(params[:account_id])
destination = Account.find(params[:destination_id])
if MoneyTransfer.new(params[:account_id], params[:destination_id], self).execute(params[:amount])
flash[:success] = "Transfer successful!"
redirect_to source
else
flash[:error] = "There was a problem."
render :transfer
end
end
end
class MoneyTransfer
def initialize(source_id, destination_id, controller)
@source = find_account(source_id).extend Transferrer
@destination = find_account(destination_id)
@listener = controller
end
def execute(amount)
@source.transfer_to(
@destination
amount.to_i,
success: -> { @controller.go_to @source },
failure: -> { @controller.display_error @source}
)
@source
end
private
def find_account(id)
Account.find(id)
end
module Transferrer
def transfer_to(destination, amount, callbacks)
transaction do
self.balance -= amount
destination.balance += amount
destination.save
self.save
callbacks[:success].call
rescue => e
callbacks[:failure].call
end
end
end
end
class TransfersController < ApplicationController
def transfer
MoneyTransfer.new(params[:account_id], params[:destination_id], self).execute(params[:amount])
end
private
def go_to(resource_or_action)
case resource_or_action
when Symbol
render resource_or_action
else
redirect_to resource_or_action
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment