After a bit of thinking I've got this implementation:
class TimelineOfEvents
attr_reader :events
class Event < Struct
def == other
self.class == Object.const_get(String(other).capitalize)
end
end
def initialize events
@events = events.collect { |event| Event(event) }
end
def Event obj
obj = obj.dup.downcase_keys!.symbolize_keys!
klass_name = obj.delete(:type).capitalize
if Object.const_defined?(klass_name)
Object.const_get(klass_name).new(*obj.values)
else
klass = Object.const_set(klass_name, Event.new(*obj.keys))
end
end
end
timeline = TimelineOfEvents.new([{ 'type' => 'playing', 'url' => '
example.org' }])
timeline.events.first == Playing