lib/emittance/event/event_builder.rb in emittance-0.0.1 vs lib/emittance/event/event_builder.rb in emittance-0.0.2

- old
+ new

@@ -1,74 +1,154 @@ -# @private -class Emittance::Event::EventBuilder - KLASS_NAME_SUFFIX = 'Event'.freeze +# frozen_string_literal: true - class << self - def object_to_klass(obj) - return obj if pass_klass_through?(obj) +module Emittance + # @private + class Event + class EventBuilder + KLASS_NAME_SUFFIX = 'Event' - klass_name = klassable_name_for obj - klass_name = dress_up_klass_name klass_name - find_or_create_event_klass klass_name - end + class << self + def klass_exists_for_identifier?(identifier) + klass_name = generate_event_klass_name identifier + !!lookup_event_klass(klass_name) + end - def klass_to_identifier(klass) - identifier_str = klass.name - identifier_str = undress_klass_name identifier_str - identifier_str = snake_case identifier_str + def objects_to_klass(*objs) + klass = nil - identifier_str.to_sym - end + klass ||= pass_klass_through(*objs) + klass ||= find_by_custom_identifier(*objs) + klass ||= generate_event_klass(*objs) - private + klass + end - def pass_klass_through?(obj) - obj.is_a?(Class) && obj < Emittance::Event - end + def klass_to_identifier(klass) + identifier = nil - def klassable_name_for(obj) - name_str = obj.to_s - name_str = camel_case name_str - name_str = clean_up_punctuation name_str + identifier ||= reverse_find_by_custom_identifier(klass) + identifier ||= convert_klass_to_identifier(klass) - name_str - end + identifier + end - def camel_case(str) - str = str.sub(/^[a-z\d]*/) { $&.capitalize } - str.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" } - end + def register_custom_identifier(klass, identifier) + CustomIdentifiers.set identifier, klass + end - def snake_case(str) - str.gsub(/::/, '_') - .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') - .gsub(/([a-z\d])([A-Z])/,'\1_\2') - .tr("-", "_") - .downcase - end + private - def clean_up_punctuation(str) - str.gsub /[^A-Za-z\d]/, '' - end + def pass_klass_through(*objs) + objs.length == 1 && objs[0].is_a?(Class) && objs[0] < Emittance::Event ? objs[0] : nil + end - def dress_up_klass_name(klass_name) - "#{klass_name}#{KLASS_NAME_SUFFIX}" - end + def find_by_custom_identifier(*objs) + if objs.length == 1 + CustomIdentifiers.event_klass_for objs[0] + else + nil + end + end - def undress_klass_name(klass_name_str) - klass_name_str.gsub /#{KLASS_NAME_SUFFIX}$/, '' - end + def reverse_find_by_custom_identifier(klass) + CustomIdentifiers.identifier_for klass + end - def find_or_create_event_klass(klass_name) - unless Object.const_defined? klass_name - create_event_klass klass_name + def generate_event_klass_name(*objs) + klass_name_parts = objs.map { |obj| klassable_name_for obj } + dress_up_klass_name klass_name_parts + end + + def generate_event_klass(*objs) + klass_name = generate_event_klass_name(*objs) + find_or_create_event_klass klass_name + end + + def convert_klass_to_identifier(klass) + identifier_str = klass.name + identifier_str = undress_klass_name identifier_str + identifier_str = snake_case identifier_str + + identifier_str.to_sym + end + + def klassable_name_for(obj) + name_str = obj.to_s + name_str = camel_case name_str + name_str = clean_up_punctuation name_str + + name_str + end + + def camel_case(str) + str = str.sub(/^[a-z\d]*/) { $&.capitalize } + str.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" } + end + + def snake_case(str) + str.gsub(/::/, '_') + .gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2') + .gsub(/([a-z\d])([A-Z])/,'\1_\2') + .tr("-", "_") + .downcase + end + + def clean_up_punctuation(str) + str.gsub /[^A-Za-z\d]/, '' + end + + def dress_up_klass_name(klass_name_parts) + "#{Array(klass_name_parts).join}#{KLASS_NAME_SUFFIX}" + end + + def undress_klass_name(klass_name_str) + klass_name_str.gsub /#{KLASS_NAME_SUFFIX}$/, '' + end + + def lookup_event_klass(klass_name) + if Object.const_defined? klass_name + Object.const_get klass_name + else + nil + end + end + + def find_or_create_event_klass(klass_name) + lookup_event_klass(klass_name) || create_event_klass(klass_name) + end + + def create_event_klass(klass_name) + new_klass = Class.new(Emittance::Event) + Object.const_set klass_name, new_klass + end end - Object.const_get klass_name - end + class CustomIdentifiers + @mappings = {} - def create_event_klass(klass_name) - new_klass = Class.new(Emittance::Event) - Object.const_set klass_name, new_klass + class << self + def mapping_exists?(identifier) + !!mappings[identifier] || Emittance::Event::EventBuilder.klass_exists_for_identifier?(identifier) + end + + def event_klass_for(identifier) + mappings[identifier] + end + + def identifier_for(event_klass) + mappings.key event_klass + end + + def set(identifier, event_klass) + raise Emittance::InvalidIdentifierError, 'Event identifiers must be a Symbol.' unless identifier.is_a? Symbol + raise Emittance::IdentifierTakenError if mapping_exists? identifier + mappings[identifier] = event_klass + end + + private + + attr_reader :mappings + end + end end end end