Skip to content

Instantly share code, notes, and snippets.

@rybex
Created September 18, 2015 12:57
Show Gist options
  • Save rybex/3d150e2e850fb5b8ea46 to your computer and use it in GitHub Desktop.
Save rybex/3d150e2e850fb5b8ea46 to your computer and use it in GitHub Desktop.
module AppServices
class AddNewTeam
include EventStore::Injector
def initialize(team_repository = ::OrganizationBc::Adapters::TeamRepository.new)
@team_repository = team_repository
end
def call(team_data)
team = create_new_team(team_data)
publish_team_created(team_data, team.id, parent.department)
team
end
private
attr_reader :team_repository
def create_new_team(team_data)
add_new_team = OrganizationBc::Teams::Services::AddNewTeam.new(team_repository)
add_new_team.(team_data)
end
def publish_team_created(team, team_id, department)
stream_name = "team/#{team_id}"
event = ::Event::TeamCreated.new({
data: {
team: {
id: team_id,
organization_id: team[:organization_id],
name: team[:name],
parent_id: team[:parent_id],
department: team[:department],
type: 'team'
}
}
})
event_store.publish_event(event, stream_name)
end
end
end
module OrganizationBc
module Teams
module Services
class AddNewTeam
def initialize(repository)
@repository = repository
end
def call(team)
team = Team.new({
id: team[:id],
name: team[:name],
organization_id: team[:organization_id]
})
repository.create(team)
end
private
attr_reader :repository
end
end
end
end
Rails.application.configure do
#other stuff
config.event_store = EventStore::SetupEventStore.new.()
end
class TeamsController < ApplicationController
before_action :authenticate_user_from_token!
def in_organization
teams = AppServices::TeamsInOrganization.new.(params[:organization_id])
render json: { teams: teams }
end
def show
AppServices::GetTeam.new.(params[:id])
end
def create
AppServices::AddNewTeam.new.(params[:team])
end
def update
AppServices::EditTeamData.new.(params[:team])
end
def destroy
AppServices::RemoveTeam.new.(params[:id])
end
end
module EventStore
module Injector
def event_store
@event_store ||= Rails.application.config.event_store
end
end
end
module AppQueries
class LoadOrganizationStructure
def initialize(repository = OrganizationBc::Adapters::StructureReadModelRepository.new)
@repository = repository
end
def call(organization_id)
repository.find_by_organization_id!(organization_id)
end
private
attr_reader :repository
end
end
module EventStore
class SetupEventStore
def call
event_store = RailsEventStore::Client.new
structure_read_model = OrganizationBc::ReadModels::Structure.new
event_store = config_structure_handler(structure_read_model, event_store)
event_store
end
private
def config_structure_handler(structure_read_model, event_store)
events = ['Event::OrganizationCreated',
'Event::MemberAdded',
'Event::MemberUpdated',
'Event::MemberDeleted',
'Event::MemberUnassigned',
'Event::TeamCreated',
'Event::TeamUpdated',
'Event::TeamRemoved']
event_store.subscribe(structure_read_model, events)
event_store
end
end
end
module OrganizationBc
module ReadModels
class Structure
def initialize(repository = ::OrganizationBc::Adapters::StructureReadModelRepository.new)
@repository = repository
end
def handle_event(event)
case event.event_type
when 'Event::OrganizationCreated'
create_structure_for_organization(event.data[:organization])
when 'Event::MemberAdded'
update_structure(event.data[:member]) { |structure, member| add_member_to_model(structure, member) }
when 'Event::MemberUpdated'
update_structure(event.data[:member]) { |structure, member| update_member_in_model(structure, member) }
when 'Event::MemberDeleted'
update_structure(event.data[:member]) { |structure, member| remove_member_from_model(structure, member) }
when 'Event::MemberUnassigned'
update_structure(event.data[:member]) { |structure, member| remove_member_from_model(structure, member) }
when 'Event::TeamCreated'
update_structure(event.data[:team]) { |structure, team| add_team_to_model(structure, team) }
when 'Event::TeamUpdated'
handle_team_updated(event)
when 'Event::TeamRemoved'
update_structure(event.data[:team]) { |structure, team| remove_team_from_model(structure, team) }
end
end
private
attr_reader :repository
def create_structure_for_organization(organization)
save_structure(organization[:id])
end
def update_structure(element)
org_structure = get_organization_structure(element[:organization_id])
yield(org_structure[:structure], element.merge!(children: []))
save_structure(element[:organization_id], org_structure)
end
def add_member_to_model(people, member)
if member[:parent_id] == ''
people.push member
else
people.each do |person|
if person['id'] == member[:parent_id]
person['children'] << member
else
add_member_to_model(person['children'], member)
end
end
end
end
def update_member_in_model(people, member)
people.each_with_index do |person, index|
if person['id'] == member[:id]
people[index] = member
else
update_member_in_model(person['children'], member)
end
end
end
def remove_member_from_model(people, member)
people.each_with_index do |person, index|
if person['id'] == member[:id]
people.delete_at(index)
else
remove_member_from_model(person['children'], member)
end
end
end
def add_team_to_model(people, team)
people.each do |person|
if person['id'] == team[:parent_id]
person['children'] << team
else
add_team_to_model(person['children'], team)
end
end
end
def handle_team_updated(event)
#code
end
def update_team_in_nodes(nodes, team)
nodes.map do |node|
if node['id'] == team[:id]
team[:children] = node['children']
team
else
node['children'] = update_team_in_nodes(node['children'], team)
node
end
end
end
def remove_team_from_model(people, team)
people.each_with_index do |person, index|
if person['id'] == team[:id]
people.delete_at(index)
else
remove_team_from_model(person['children'], team)
end
end
end
def get_organization_structure(organization_id)
record = repository.find_by_organization_id!(organization_id)
{structure: record.model['structure'], departments: record.model['departments'], version: record.version}
end
def save_structure(organization_id, model = {structure: [], departments: [], version: 0})
repository.create(organization_id, model)
end
end
end
end
module OrganizationBc
module Adapters
class StructureReadModelRepository
class StructureReadModel < ActiveRecord::Base
self.table_name = 'structures_read_models'
end
ReadModelNotFound = Class.new(StandardError)
def create(organization_id, model)
version = model[:version] + 1
model[:version] = version
record = StructureReadModel.new({ organization_id: organization_id, version: version, model: model})
record.save!
end
def find_by_organization_id!(organization_id)
record = find_by_organization_id(organization_id)
raise ReadModelNotFound.new if record.nil?
record
end
private
def find_by_organization_id(organization_id)
StructureReadModel.where(organization_id: organization_id).order(:version).last
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment