Решение вашего первого вопроса.Вот некоторые идеи, которые вы могли бы рассмотреть
Во-первых, структурируйте свои подклассы так, чтобы они все использовали одинаковые параметры инициации.Кроме того, вы могли бы поместить туда и другой исходный код (например, свои encoded_body и серверные средства доступа. Вот скелет того, что я имею в виду:
# SOChat Class skeleton structure
class SOChatSubClass #< inherit from whatever parent class is appropriate
attr_accessor :encoded_body, :server, :from, :to, :body
def initialize(event, room, server)
@encoded_body = event['content']
@server = server
SOChatEvent.events.push event
#class specific code
xmpp_message = event['message']
@from = xmpp_message.from
@to = xmpp_message.to
@body = xmpp_message.body
#use super to call parent class initialization methods and to DRY up your code
end
end
Обратите внимание, что в моем примере вы все равно будете иметьдублированный код в подклассах. В идеале вы должны удалить дубликаты, поместив их в соответствующий родительский класс.
Если у вас возникли проблемы при создании общего списка параметров инициации, то вместо передачи спискааргументов (событие, комната, сервер), измените классы так, чтобы они принимали список аргументов как хэш {: событие => событие,: комната => комната,: сервер => сервер и т. д.}.
Независимо от того,если у вас есть общая структура параметров для инициализации классов, вы можете инициализировать их более динамично, что устраняет необходимость в операторе case.
class SOChatEvent
class << self; attr_accessor :events; end
@events = []
@@event_parser = {
0 => SOChatSubClass, #hypothetical example for testing
1 => SOChatMessage,
2 => SOChatMessageEdit,
#etc
}
def self.create_from_evt( json_event_data, room=nil, server=nil)
event_type = json_event_data["event_type"]
event_class = @@event_parser[event_type]
#this creates the class defined by class returned in the @@event_parser hash
event_obj = event_class.new(json_event_data, room, server)
end
#rest of class
end
@@event_parser
содержит отображение между типом события икласс для реализации этого типа события. Вы просто присваиваете соответствующий класс переменной и обрабатываете его как фактический класс.
Код, подобный следующему, создаст объект соответствующего класса:
event_obj = SOChatEvent.create_from_evt( json_event_data,
"some room",
"some server")
Примечание: есть дополнительные оптимизации, которые я мог бы сделать, чтобы то, что я предоставил, было еще чище и более кратким, но, надеюсь, это поможетВы преодолеваете горстку оператора case.
Редактировать: я забыл упомянуть переменную экземпляра класса SOChatEvent.events
, созданную с помощью этого: class << self; attr_accessor :events; end
@events = []
Вы помещали события в стек событий, но мне было непонятно, где вы хотели, чтобы этот стек существовал, и был ли это глобальный список событий или специфический для определенного класса.Тот, который я сделал, является глобальным, поэтому смело изменяйте его, если хотите, чтобы стек событий ограничивался определенными классами или экземплярами.