rcqrs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -0
 - data/.rspec +2 -0
 - data/Gemfile +4 -0
 - data/README.md +4 -0
 - data/Rakefile +1 -0
 - data/lib/rcqrs.rb +30 -0
 - data/lib/rcqrs/aggregate_root_base.rb +70 -0
 - data/lib/rcqrs/base_command.rb +22 -0
 - data/lib/rcqrs/base_command_handler.rb +27 -0
 - data/lib/rcqrs/base_event.rb +57 -0
 - data/lib/rcqrs/command_executor.rb +16 -0
 - data/lib/rcqrs/command_not_valid_exception.rb +13 -0
 - data/lib/rcqrs/command_source.rb +72 -0
 - data/lib/rcqrs/configuration.rb +15 -0
 - data/lib/rcqrs/convention_command.rb +32 -0
 - data/lib/rcqrs/convention_command_handler.rb +33 -0
 - data/lib/rcqrs/denormalizer.rb +79 -0
 - data/lib/rcqrs/domain_exception.rb +11 -0
 - data/lib/rcqrs/event_bus.rb +59 -0
 - data/lib/rcqrs/event_collection.rb +18 -0
 - data/lib/rcqrs/event_configuration_base.rb +43 -0
 - data/lib/rcqrs/event_handler.rb +55 -0
 - data/lib/rcqrs/event_type_registry.rb +16 -0
 - data/lib/rcqrs/not_an_event_exception.rb +7 -0
 - data/lib/rcqrs/published_event.rb +15 -0
 - data/lib/rcqrs/repository.rb +27 -0
 - data/lib/rcqrs/unknown_event_exception.rb +3 -0
 - data/lib/rcqrs/version.rb +3 -0
 - data/rcqrs.gemspec +29 -0
 - data/spec/aggregate_root_base_spec.rb +69 -0
 - data/spec/base_commandhandler_spec.rb +38 -0
 - data/spec/base_event_spec.rb +26 -0
 - data/spec/command_executor_spec.rb +12 -0
 - data/spec/command_handler_spec.rb +40 -0
 - data/spec/configuration_spec.rb +13 -0
 - data/spec/convention_command_spec.rb +33 -0
 - data/spec/denormalizer_spec.rb +107 -0
 - data/spec/eventbus_spec.rb +109 -0
 - data/spec/eventhandler_spec.rb +74 -0
 - data/spec/repository_spec.rb +75 -0
 - data/spec/ricko.rb +181 -0
 - data/spec/spec_helper.rb +29 -0
 - data/spec/test_aggregate.rb +36 -0
 - data/spec/test_command_handler.rb +33 -0
 - data/spec/test_command_source.rb +4 -0
 - data/spec/test_event.rb +13 -0
 - data/spec/test_event_bus.rb +18 -0
 - metadata +154 -0
 
| 
         @@ -0,0 +1,59 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rcqrs
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class Eventbus
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize eventstore
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @eventstore = eventstore
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @eventhandlers = Hash.new
         
     | 
| 
      
 8 
     | 
    
         
            +
                  @published_events = Array.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                end
         
     | 
| 
      
 10 
     | 
    
         
            +
                
         
     | 
| 
      
 11 
     | 
    
         
            +
                def load_events aggregate_id
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @eventstore.load_events(aggregate_id)
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
                
         
     | 
| 
      
 15 
     | 
    
         
            +
                def register eventtype, eventhandler
         
     | 
| 
      
 16 
     | 
    
         
            +
                  @eventhandlers[eventtype] = Array.new unless @eventhandlers.has_key? eventtype
         
     | 
| 
      
 17 
     | 
    
         
            +
                  unless @eventhandlers[eventtype].include? eventhandler
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @eventhandlers[eventtype] << eventhandler      
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
                
         
     | 
| 
      
 22 
     | 
    
         
            +
                def publish id, event
         
     | 
| 
      
 23 
     | 
    
         
            +
                  unless event.is_a? BaseEvent then
         
     | 
| 
      
 24 
     | 
    
         
            +
                    raise NotAnEventException, "Given event has to inherit from BaseEvent"
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @published_events << PublishedEvent.new(id,event)
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
                
         
     | 
| 
      
 29 
     | 
    
         
            +
                def commit
         
     | 
| 
      
 30 
     | 
    
         
            +
                  store_published_time_for_events
         
     | 
| 
      
 31 
     | 
    
         
            +
                  save_events
         
     | 
| 
      
 32 
     | 
    
         
            +
                  publish_events
         
     | 
| 
      
 33 
     | 
    
         
            +
                  flush
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
                
         
     | 
| 
      
 36 
     | 
    
         
            +
                private
         
     | 
| 
      
 37 
     | 
    
         
            +
                
         
     | 
| 
      
 38 
     | 
    
         
            +
                def store_published_time_for_events
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @published_events.each{|published_event| published_event.event.store_publish_time}
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
                
         
     | 
| 
      
 42 
     | 
    
         
            +
                def save_events
         
     | 
| 
      
 43 
     | 
    
         
            +
                  @eventstore.store(@published_events)
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
                
         
     | 
| 
      
 46 
     | 
    
         
            +
                def publish_events
         
     | 
| 
      
 47 
     | 
    
         
            +
                  @published_events.each do |event_tuple|
         
     | 
| 
      
 48 
     | 
    
         
            +
                    if @eventhandlers[event_tuple.event.class] != nil
         
     | 
| 
      
 49 
     | 
    
         
            +
                      @eventhandlers[event_tuple.event.class].each {|handler| handler.handle event_tuple.aggregate_id, event_tuple.event }
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end      
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
                
         
     | 
| 
      
 54 
     | 
    
         
            +
                def flush
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @published_events = Array.new
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rcqrs
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class EventCollection
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                def initialize aggregateroot_id, events    
         
     | 
| 
      
 6 
     | 
    
         
            +
                  @events = events
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @aggregateroot_id = aggregateroot_id   
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
                
         
     | 
| 
      
 10 
     | 
    
         
            +
                def commit_to eventstore
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @events.each do |event|
         
     | 
| 
      
 12 
     | 
    
         
            +
                    eventstore.publish @aggregateroot_id, event
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
                
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,43 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rcqrs
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class EventConfigurationBase
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @configs = Array.new
         
     | 
| 
      
 6 
     | 
    
         
            +
                
         
     | 
| 
      
 7 
     | 
    
         
            +
                def self.register_handler(handler)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  handler.handled_events.each do |event_name|      
         
     | 
| 
      
 9 
     | 
    
         
            +
                    handle(event_name).with(handler)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
                
         
     | 
| 
      
 13 
     | 
    
         
            +
                def self.register_all_at(eventbus)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  if(@configs != nil)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @configs.each do |config| 
         
     | 
| 
      
 16 
     | 
    
         
            +
                      eventbus.register config.eventtype, config.eventhandler
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
                
         
     | 
| 
      
 21 
     | 
    
         
            +
                def self.handle(eventtype)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @configs = Array.new if (@configs == nil)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  config = EventConfig.new(eval(eventtype.to_s))
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @configs << config
         
     | 
| 
      
 25 
     | 
    
         
            +
                  config
         
     | 
| 
      
 26 
     | 
    
         
            +
                end    
         
     | 
| 
      
 27 
     | 
    
         
            +
                
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
              
         
     | 
| 
      
 30 
     | 
    
         
            +
              class EventConfig
         
     | 
| 
      
 31 
     | 
    
         
            +
                
         
     | 
| 
      
 32 
     | 
    
         
            +
                attr_reader :eventtype, :eventhandler
         
     | 
| 
      
 33 
     | 
    
         
            +
                
         
     | 
| 
      
 34 
     | 
    
         
            +
                def initialize eventtype
         
     | 
| 
      
 35 
     | 
    
         
            +
                  @eventtype = eventtype
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
                
         
     | 
| 
      
 38 
     | 
    
         
            +
                def with eventhandler
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @eventhandler = eventhandler
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,55 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rcqrs
         
     | 
| 
      
 2 
     | 
    
         
            +
              
         
     | 
| 
      
 3 
     | 
    
         
            +
              module EventHandler
         
     | 
| 
      
 4 
     | 
    
         
            +
                
         
     | 
| 
      
 5 
     | 
    
         
            +
                def self.included(base)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  base.extend(ClassMethods)
         
     | 
| 
      
 7 
     | 
    
         
            +
                end
         
     | 
| 
      
 8 
     | 
    
         
            +
                
         
     | 
| 
      
 9 
     | 
    
         
            +
                module ClassMethods
         
     | 
| 
      
 10 
     | 
    
         
            +
                  
         
     | 
| 
      
 11 
     | 
    
         
            +
                  def handled_events
         
     | 
| 
      
 12 
     | 
    
         
            +
                    methods.select {|m| m.to_s.match(/^handle_/)}.map{|m| convert_to_event_name(m[6..-1])}
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
                  
         
     | 
| 
      
 15 
     | 
    
         
            +
                  def convert_to_event_name method
         
     | 
| 
      
 16 
     | 
    
         
            +
                    full_event_name(method)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  
         
     | 
| 
      
 19 
     | 
    
         
            +
                  def handle aggregate_id, event
         
     | 
| 
      
 20 
     | 
    
         
            +
                   methodname = handler_method_name(event)
         
     | 
| 
      
 21 
     | 
    
         
            +
                   send(methodname, aggregate_id,event)
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                              
         
     | 
| 
      
 24 
     | 
    
         
            +
                  def handler_method_name(event)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    "handle" + event.class.name.split("::").last.gsub(/[A-Z]/){|s| "_" + s.downcase}
         
     | 
| 
      
 26 
     | 
    
         
            +
                  end
         
     | 
| 
      
 27 
     | 
    
         
            +
                        
         
     | 
| 
      
 28 
     | 
    
         
            +
                  def namespace namespace
         
     | 
| 
      
 29 
     | 
    
         
            +
                    @namespace = namespace.to_s + "::"
         
     | 
| 
      
 30 
     | 
    
         
            +
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  
         
     | 
| 
      
 32 
     | 
    
         
            +
                  def handler(event, &handlercode)
         
     | 
| 
      
 33 
     | 
    
         
            +
                    create_handler_method(event,handlercode)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    EventConfigurationBase.handle(full_event_name(event)).with(self)
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                  
         
     | 
| 
      
 37 
     | 
    
         
            +
                  def full_event_name event_name
         
     | 
| 
      
 38 
     | 
    
         
            +
                    (@namespace || "") + symbol_to_event_name(event_name)
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                  
         
     | 
| 
      
 41 
     | 
    
         
            +
                  def symbol_to_event_name event
         
     | 
| 
      
 42 
     | 
    
         
            +
                    name = event.to_s.gsub(/_[a-z]/){|s| s[1].upcase}
         
     | 
| 
      
 43 
     | 
    
         
            +
                    name[0] = name[0].upcase
         
     | 
| 
      
 44 
     | 
    
         
            +
                    name
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def create_handler_method(event,handlercode)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    itself = (class << self; self; end)             
         
     | 
| 
      
 49 
     | 
    
         
            +
                    itself.instance_eval do
         
     | 
| 
      
 50 
     | 
    
         
            +
                      define_method "handle_"+event.to_s.gsub(/[A-Z]/){|s| "_" + s.downcase}, &handlercode
         
     | 
| 
      
 51 
     | 
    
         
            +
                    end
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end      
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              end 
         
     | 
| 
      
 55 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,15 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rcqrs
         
     | 
| 
      
 2 
     | 
    
         
            +
              
         
     | 
| 
      
 3 
     | 
    
         
            +
              class PublishedEvent
         
     | 
| 
      
 4 
     | 
    
         
            +
                attr_accessor :aggregate_id, :event
         
     | 
| 
      
 5 
     | 
    
         
            +
                
         
     | 
| 
      
 6 
     | 
    
         
            +
                def initialize aggregate_id, event
         
     | 
| 
      
 7 
     | 
    
         
            +
                  @aggregate_id, @event = aggregate_id, event   
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
                
         
     | 
| 
      
 10 
     | 
    
         
            +
                def ==(other)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  @aggregate_id == other.aggregate_id && @event == other.event
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
              
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Rcqrs
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Repository
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def initialize event_store
         
     | 
| 
      
 5 
     | 
    
         
            +
                  @event_store = event_store
         
     | 
| 
      
 6 
     | 
    
         
            +
                end
         
     | 
| 
      
 7 
     | 
    
         
            +
                
         
     | 
| 
      
 8 
     | 
    
         
            +
                def load(aggregate_class, aggregate_id)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  aggregate = aggregate_class.new aggregate_id
         
     | 
| 
      
 10 
     | 
    
         
            +
                  events = @event_store.load_events(aggregate_id)
         
     | 
| 
      
 11 
     | 
    
         
            +
                  aggregate.load_from(events)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  aggregate
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
                
         
     | 
| 
      
 15 
     | 
    
         
            +
                def save aggregate_root
         
     | 
| 
      
 16 
     | 
    
         
            +
                  aggregate_root.pending_events.commit_to @event_store
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
                
         
     | 
| 
      
 19 
     | 
    
         
            +
                def fire aggregate_id, event
         
     | 
| 
      
 20 
     | 
    
         
            +
                  unless (event.is_a? BaseEvent) then
         
     | 
| 
      
 21 
     | 
    
         
            +
                    raise NotAnEventException, "Given event has to inherit from BaseEvent"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @event_store.publish(aggregate_id,event)
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
              
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
    
        data/rcqrs.gemspec
    ADDED
    
    | 
         @@ -0,0 +1,29 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            $:.push File.expand_path("../lib", __FILE__)
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "rcqrs/version"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 6 
     | 
    
         
            +
              s.name        = "rcqrs"
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.version     = Rcqrs::VERSION
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.authors     = ["Tim de Putter"]
         
     | 
| 
      
 9 
     | 
    
         
            +
              s.email       = ["tim.de.putter83@googlemail.com"]
         
     | 
| 
      
 10 
     | 
    
         
            +
              s.summary     = %q{Framework to provide cqrs + eventsourcing functionality in ruby.}
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.description = %q{Framework to provide cqrs + eventsourcing functionality in ruby.}
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              s.rubyforge_project = "rcqrs"
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              s.files         = `git ls-files`.split("\n")
         
     | 
| 
      
 16 
     | 
    
         
            +
              s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
         
     | 
| 
      
 17 
     | 
    
         
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              # specify any dependencies here; for example:
         
     | 
| 
      
 21 
     | 
    
         
            +
              # s.add_runtime_dependency "rest-client"
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
              s.add_development_dependency "rspec"
         
     | 
| 
      
 24 
     | 
    
         
            +
              s.add_development_dependency "rspec-spies"
         
     | 
| 
      
 25 
     | 
    
         
            +
              s.add_development_dependency "activemodel"
         
     | 
| 
      
 26 
     | 
    
         
            +
              s.add_runtime_dependency "uuid"
         
     | 
| 
      
 27 
     | 
    
         
            +
              
         
     | 
| 
      
 28 
     | 
    
         
            +
              
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,69 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Rcqrs::AggregateRootBase do 
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              before do
         
     | 
| 
      
 6 
     | 
    
         
            +
                @idgenerator = UUID.new
         
     | 
| 
      
 7 
     | 
    
         
            +
                @id = @idgenerator.generate
         
     | 
| 
      
 8 
     | 
    
         
            +
                @testAggregate = TestAggregateModule::TestAggregate.new @id
         
     | 
| 
      
 9 
     | 
    
         
            +
                @mockEventStore = mockup
         
     | 
| 
      
 10 
     | 
    
         
            +
                @events = [TestEventModule::TestEvent.new, TestEventModule::TestEvent.new]
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it "should handle Events" do
         
     | 
| 
      
 14 
     | 
    
         
            +
                @testAggregate.doSomething
         
     | 
| 
      
 15 
     | 
    
         
            +
                @testAggregate.handledEvents.size.should == 1
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              it "should events when there is no eventhandler method" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                class UnknownEvent < Rcqrs::BaseEvent; end
         
     | 
| 
      
 20 
     | 
    
         
            +
                @testAggregate.load_from [TestEventModule::TestEvent.new,UnknownEvent.new]
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
              
         
     | 
| 
      
 23 
     | 
    
         
            +
              it "should collect Events in a EventCollection" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                @testAggregate.doSomething
         
     | 
| 
      
 25 
     | 
    
         
            +
                @testAggregate.pending_events.should be_an_instance_of(Rcqrs::EventCollection)
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              it "should have recorded one event to be committed" do
         
     | 
| 
      
 29 
     | 
    
         
            +
                @testAggregate.doSomething
         
     | 
| 
      
 30 
     | 
    
         
            +
                @testAggregate.pending_events.commit_to @mockEventStore        
         
     | 
| 
      
 31 
     | 
    
         
            +
                @mockEventStore.message(:publish).with(any, any(TestEventModule::TestEvent)).should_be_received
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
              
         
     | 
| 
      
 34 
     | 
    
         
            +
              it "should send its uuid to eventstore to be able to assoziate the events with the aggregate" do
         
     | 
| 
      
 35 
     | 
    
         
            +
                @testAggregate.doSomething
         
     | 
| 
      
 36 
     | 
    
         
            +
                @testAggregate.pending_events.commit_to @mockEventStore
         
     | 
| 
      
 37 
     | 
    
         
            +
                @mockEventStore.message(:publish).with(@id, any()).should_be_received   
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
              
         
     | 
| 
      
 40 
     | 
    
         
            +
              it "should be able to load from existing events in the eventstore" do
         
     | 
| 
      
 41 
     | 
    
         
            +
                @testAggregate.load_from @events
         
     | 
| 
      
 42 
     | 
    
         
            +
                @testAggregate.handledEvents[0] == @events[0]
         
     | 
| 
      
 43 
     | 
    
         
            +
                @testAggregate.handledEvents[1] == @events[1]
         
     | 
| 
      
 44 
     | 
    
         
            +
              end  
         
     | 
| 
      
 45 
     | 
    
         
            +
              
         
     | 
| 
      
 46 
     | 
    
         
            +
              it "should only pass the new events to the eventstore, not the ones loaded previously" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                @testAggregate.load_from @events
         
     | 
| 
      
 48 
     | 
    
         
            +
                @testAggregate.doSomething
         
     | 
| 
      
 49 
     | 
    
         
            +
                @testAggregate.pending_events.commit_to @mockEventStore
         
     | 
| 
      
 50 
     | 
    
         
            +
                @mockEventStore.message(:publish).with(@id,any(TestEventModule::TestEvent)).should_be_received
         
     | 
| 
      
 51 
     | 
    
         
            +
              end
         
     | 
| 
      
 52 
     | 
    
         
            +
              
         
     | 
| 
      
 53 
     | 
    
         
            +
              it "events not inherited from BaseEvent are not allowed to be fired" do
         
     | 
| 
      
 54 
     | 
    
         
            +
                expect {@testAggregate.doSomethingStupid}.to raise_error(Rcqrs::NotAnEventException)
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
              
         
     | 
| 
      
 57 
     | 
    
         
            +
              it "should allow to define eventhandlers via a class macro" do
         
     | 
| 
      
 58 
     | 
    
         
            +
                @testAggregate.handleAnotherTestEvent TestEventModule::AnotherTestEvent.new
         
     | 
| 
      
 59 
     | 
    
         
            +
                @testAggregate.handledEvents[0].class.should == TestEventModule::AnotherTestEvent
         
     | 
| 
      
 60 
     | 
    
         
            +
              end
         
     | 
| 
      
 61 
     | 
    
         
            +
              
         
     | 
| 
      
 62 
     | 
    
         
            +
              it "should handle events with eventhandlers defined by class macros" do
         
     | 
| 
      
 63 
     | 
    
         
            +
                @testAggregate.do_something_else
         
     | 
| 
      
 64 
     | 
    
         
            +
                @testAggregate.handledEvents[0].class.should == TestEventModule::AnotherTestEvent    
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,38 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "spec_helper"
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Rcqrs::BaseCommandHandler do
         
     | 
| 
      
 4 
     | 
    
         
            +
              
         
     | 
| 
      
 5 
     | 
    
         
            +
              it "should call execute on inherited class when executeCommand is called" do
         
     | 
| 
      
 6 
     | 
    
         
            +
                commandHandler = TestCommandHandler.new nil
         
     | 
| 
      
 7 
     | 
    
         
            +
                commandHandler.executeCommand TestCommand.new("param")
         
     | 
| 
      
 8 
     | 
    
         
            +
                commandHandler.execute_called?.should == true
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
              it "should validate the given command if it provides validation" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                commandHandler = TestCommandHandler.new nil
         
     | 
| 
      
 13 
     | 
    
         
            +
                testCommand = TestCommand.new("param")
         
     | 
| 
      
 14 
     | 
    
         
            +
                def testCommand.invalid?; true; end
         
     | 
| 
      
 15 
     | 
    
         
            +
                expect {commandHandler.executeCommand testCommand}.to raise_error Rcqrs::CommandNotValidException
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
              
         
     | 
| 
      
 18 
     | 
    
         
            +
              it "the validation does not fail the command is executed" do
         
     | 
| 
      
 19 
     | 
    
         
            +
                commandHandler = TestCommandHandler.new nil
         
     | 
| 
      
 20 
     | 
    
         
            +
                testCommand = TestCommand.new("param")
         
     | 
| 
      
 21 
     | 
    
         
            +
                def testCommand.invalid?; false; end
         
     | 
| 
      
 22 
     | 
    
         
            +
                commandHandler.executeCommand testCommand
         
     | 
| 
      
 23 
     | 
    
         
            +
                commandHandler.execute_called?.should == true 
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
              
         
     | 
| 
      
 26 
     | 
    
         
            +
              it "should put all validationerrors in the Exception if the validation fails" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                begin
         
     | 
| 
      
 28 
     | 
    
         
            +
                  commandHandler = TestCommandHandler.new nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                  testCommand = TestCommand.new("param")
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def testCommand.invalid?; true; end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def testCommand.errormessages; ["Error1", "Error2"]; end
         
     | 
| 
      
 32 
     | 
    
         
            +
                  commandHandler.executeCommand testCommand
         
     | 
| 
      
 33 
     | 
    
         
            +
                rescue Rcqrs::CommandNotValidException => exception
         
     | 
| 
      
 34 
     | 
    
         
            +
                  exception.errors.should == ["Error1", "Error2"]
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
              
         
     | 
| 
      
 38 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            describe Rcqrs::BaseEvent do
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
              class TestEvent < Rcqrs::BaseEvent
         
     | 
| 
      
 4 
     | 
    
         
            +
                property :name
         
     | 
| 
      
 5 
     | 
    
         
            +
              end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              subject{TestEvent}
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              it "should allow to define properties on an event which can be initalized in the constructor" do
         
     | 
| 
      
 10 
     | 
    
         
            +
                TestEvent.new(name: "Timbo").name.should == "Timbo"
         
     | 
| 
      
 11 
     | 
    
         
            +
              end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
              it "should allow to use strings as keys" do
         
     | 
| 
      
 14 
     | 
    
         
            +
                TestEvent.new("name" => "Timbo").name.should == "Timbo"
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              it "should reject properties not defined" do
         
     | 
| 
      
 18 
     | 
    
         
            +
                lambda {TestEvent.new(age: 23)}.should raise_error
         
     | 
| 
      
 19 
     | 
    
         
            +
                lambda {TestEvent.new("age" =>  23)}.should raise_error
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              it "should not allow to define allready used methods as properties" do
         
     | 
| 
      
 23 
     | 
    
         
            +
                lambda {class TestEvent; property :data ;end}.should raise_error
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     |