views:

118

answers:

3

hi! I have an Event class which holds start and end times for an event. Each Event object can have a number of associated ChildEvent objects representing each recurrence of the parent Event. Each of those classes needs to take a different action based on how they are being edited e.g.

Deleting just one Event:

  • Event: make the first child the parent of all other children before deleting
  • ChildEvent: just delete as normal

Deleting an Event and all subsequent events:

  • Event: delete all child events then delete itself
  • ChildEvent: delete all future siblings then delete itself

Editing just one Event:

  • Event: make the first child the parent of all other children then update
  • ChildEvent: update itself as usual

Editing an Event and all subsequent events:

  • Event: update all child events then update itself
  • ChildEvent: update all future siblings then update itself

At present I'm achieving this through checking for conditions and taking appropriate action but it's starting to get messy (there are other conditions with associated behaviours too). I'm curious to know how more experienced programmers would handle this (I'm using ruby). Any ideas?

+2  A: 

Sounds like a case for the specification pattern to encapsulate your logic

Andrew Bullock
A: 

Why don't you just link the events, in the form of a doubly linked list?

An Event would have a previous and a next slot (nil if first or last of a chain).

Deleting just one Event (delete):

  • set the previous slot of next Event to the previous slot of this Event
  • set the next slot of the previous Event to the next slot of this Event
  • delete this Event

Deleting an Event and all subsequent events (delete-all):

  • Delete this Event
  • set next slot of previous Event to nil
  • recurse on next Event
  • until next is nil

Editing just one Event (edit):

  • edit this Event
  • set previous slot of next Event to previous slot of this Event
  • set next slot of previous Event to next slot of this Event

Editing an Event and all subsequent events (edit-all):

  • if initial call, set next slot of previous Event to nil
  • edit this Event
  • recurse on next Event
  • until next is nil
Svante
A: 

I suggest trying a different object model. Instead of Events and ChildEvents you could look at it as EventTypes and Events.

EventType  # Has many Events
---------
name
# ...

Event      # Belongs to EventType
-----
event_id
start_time
end_time
# ...

Then your editing operations would be greatly simplified.

Find previous Event...

Event.find(:first, :conditions => [
  'event_type_id = ? AND start_time > ?',
  event.type.id,
  event.start_time],
  :order => 'ASC'
)

Delete an Event and all subsequent events of that type...

events_to_delete = Event.find(:all, 
  :conditions => [
    'event_type_id = ? AND start_time >= ?', 
    event.event_type.id,
    event.start_time
  ])

Event.destroy( all_events_to_delete.map { |event| event.id } )
Ethan