Ruby Loves DDD (Part 5)

Going back to the handler. We saw in a previous post how the repository recreates the aggregate state re-executing the events. Now that we have the aggregate reference we can call methods on it:

class AddToBasketHandler
  def execute(add_to_basket_command)
    #repository creates the basket reloading all the events
    basket = @repository.get_basket(add_to_basket_command.basket_id)
    # now we can operate on basket
    basket.add_item (add_to_basket_command.article_id) 
  # more code here...

In the above example we are adding a new item to the basket using the method add_item. Now we will see how the add_item is implemented in the basket object:

def add_item (item)
  raise_event :item_added, item

The implementation is quite curious, all that it does is raising an event calling the method raise_event passing a symbol that specify the event name and the item to add.

The raise_event method is provided by the AggregateRootHelper a module included in the Basket class:

def raise_event(event_name, *args)
  uncommited_events << {name: event_name, args: args}
  send "on_#{event_name}", *args

It collect the event information inside an array of “uncommited events” and then dynamically call a method called on_item_added passing the event arguments.

def on_item_added item
  get_item(item).try(:increase_quantity) || @items <<      

The on_item_added event on basket class is where the job is really done: it increase the quantity of the item if it is already present in the basket otherwise it creates a new item.

You may ask why should be so complecated add an item the the basket?

The raise_event is necessary because the storage is event based not status based, so raising the event is important to track the fact that a new item is being added and the uncommitted_events array in the module is there to store this event (and to persist them later). The event raised could also be useful if we wan to inform other aggregates of the fact the a new item is added: for example a warehouse aggregate could receive the message to manage the available quantity.