Skip to content

Instantly share code, notes, and snippets.

@sebastiangeiger
Created September 17, 2014 18:34
Show Gist options
  • Save sebastiangeiger/b9dd30e29f37c797d8e6 to your computer and use it in GitHub Desktop.
Save sebastiangeiger/b9dd30e29f37c797d8e6 to your computer and use it in GitHub Desktop.
require 'rspec'
require 'pry'
require_relative "../lib/application"
describe 'Updating the application model' do
let(:sf) { Port.new(city: "San Francisco", country: :USA) }
let(:la) { Port.new(city: "Los Angeles", country: :USA) }
let(:yyv) { Port.new(city: "Vancouver", country: :Canada) }
let(:ship) { Ship.new("King Roy") }
let(:refactoring_books) { Cargo.new("Refactoring") }
let(:event_processor) { EventProcessor.new }
it 'sets the ships location on arrival' do
event = ArrivalEvent.new(date: Time.new(2005,11,01), ship: ship, port: sf)
event_processor.process(event)
expect(ship.location).to eql sf
end
it 'puts the ship at sea when departing from a port' do
events = [
ArrivalEvent.new( date: Time.new(2005,10,01), ship: ship, port: la),
ArrivalEvent.new( date: Time.new(2005,11,01), ship: ship, port: sf),
DepartureEvent.new(date: Time.new(2005,11,01), ship: ship, port: sf)
]
event_processor.process(events)
expect(ship.location).to eql :at_sea
end
describe 'keeping track of Canada' do
it 'records that it has not been to canda' do
events = [
LoadEvent.new( date: Time.new(2005,11,01), ship: ship, cargo: refactoring_books),
DepartureEvent.new(date: Time.new(2005,11,02), ship: ship, port: la),
ArrivalEvent.new( date: Time.new(2005,11,24), ship: ship, port: sf),
UnloadEvent.new( date: Time.new(2005,11,25), ship: ship, cargo: refactoring_books)
]
event_processor.process(events)
expect(refactoring_books).to_not have_been_in_canada
end
it 'records that it passed through Canada' do
events = [
LoadEvent.new( date: Time.new(2005,11,01), ship: ship, cargo: refactoring_books),
DepartureEvent.new(date: Time.new(2005,11,02), ship: ship, port: la),
ArrivalEvent.new( date: Time.new(2005,11,13), ship: ship, port: yyv),
DepartureEvent.new(date: Time.new(2005,11,14), ship: ship, port: yyv),
ArrivalEvent.new( date: Time.new(2005,11,24), ship: ship, port: sf),
UnloadEvent.new( date: Time.new(2005,11,25), ship: ship, cargo: refactoring_books)
]
event_processor.process(events)
expect(refactoring_books).to have_been_in_canada
end
end
end
# 1. Events
class DomainEvent
attr_reader :recorded, :occurred
def initialize(occurred: Time.now)
@occurred = occurred
@recorded = Time.now
end
end
class ShipMovementEvent< DomainEvent
attr_reader :date, :port, :ship
def initialize(date: Date.today, port:, ship: )
super(occurred: date)
@port = port
@ship = ship
end
end
class ArrivalEvent < ShipMovementEvent
def process
@ship.handle_arrival(self)
end
end
class DepartureEvent < ShipMovementEvent
def process
@ship.handle_departure(self)
end
end
class CargoEvent < DomainEvent
attr_reader :date, :cargo, :ship
def initialize(date: Date.today, cargo:, ship: )
super(occurred: date)
@cargo = cargo
@ship = ship
end
end
class LoadEvent < CargoEvent
def process
@ship.handle_load(self)
end
end
class UnloadEvent < CargoEvent
def process
@ship.handle_unload(self)
end
end
class EventProcessor
def initialize
@event_list = []
end
def process(events)
events = Array(events)
events.sort_by(&:occurred).each(&:process)
@event_list += events
end
end
# 2. Domain Models
class Ship < Struct.new(:name)
attr_reader :location
def initialize(name)
super(name)
@location = :unknown
@cargo = Set.new
end
def handle_arrival(event)
@location = event.port
@cargo.each {|c| c.handle_arrival(event)}
end
def handle_departure(event)
@location = :at_sea
@cargo.each {|c| c.handle_departure(event)}
end
def handle_load(event)
@cargo.add(event.cargo)
end
def handle_unload(event)
@cargo.delete(event.cargo)
end
end
class Port
attr_reader :city, :country
def initialize(city:, country: )
@city = city
@country = country
end
end
class Cargo < Struct.new(:name)
def initialize(name)
super(name)
@has_been_in_canada = false
end
def has_been_in_canada?
@has_been_in_canada
end
def handle_arrival(event)
@has_been_in_canada = true if event.port.country == :Canada
end
def handle_departure(event); end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment