Sha256: 7c825674e3062aaa77937dd2c93dfab22fa45ca1702e0731c53b7ab5d7ffa088

Contents?: true

Size: 1.96 KB

Versions: 1

Compression:

Stored size: 1.96 KB

Contents

# frozen_string_literal: true

require "dry-transformer"
require "json"

module DjiMqttConnect
  module Sys::Product
    class StatusMarshal < MessageMarshal
      # Rename pesky `method` argument to `_method` and makes a copy of the raw data
      class AttributeTransformer < Dry::Transformer::Pipe
        import Dry::Transformer::HashTransformations

        define! do
          symbolize_keys

          copy_keys data: :_data
          rename_keys method: :_method
        end
      end

      # Attempts to look a the method attribute, and builds a specific Message class for the message
      def load(raw_message)
        # Parse the message from JSON
        parsed_message = JSON.parse(raw_message)

        # Transform the message
        transformed_message = attribute_transformer.call(parsed_message)

        # Build an instance of the class, or a generic message from the current class
        message_class = message_class_for_parsed_message(parsed_message)
        message_class.new transformed_message
      rescue JSON::ParserError => e
        raise ParseError.new(e, "Unable to parse message as JSON")
      rescue Dry::Struct::Error => e
        raise ParseError.new(e, "Unexpected #{message_class} payload")
      end

      private

      def attribute_transformer
        @attribute_transformer ||= AttributeTransformer.new
      end

      def message_class_for_parsed_message(parsed_message)
        # update_topo => UpdateTopo
        classified_method = ActiveSupport::Inflector.classify(parsed_message["method"])

        # UpdateTopo => DjiMqttConnect::Sys::Product::UpdateTopoStatusMessage
        module_prefix, joiner, class_suffix = StatusMessage.name.rpartition("::")
        message_class_name = [module_prefix, joiner, classified_method, class_suffix].join

        # Constantize an instance of the message-specific class, or fallback to a generic message
        ActiveSupport::Inflector.safe_constantize(message_class_name) || StatusMessage
      end
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
dji_mqtt_connect-0.1.0 lib/dji_mqtt_connect/marshals/sys/product/status_marshal.rb