Module: Shikibu::TypedPayload

Defined in:
lib/shikibu/typed_payload.rb

Overview

Module to detect and handle typed payload classes Supports dry-struct, Ruby 3.2+ Data classes, and duck-typed objects

Examples:

with dry-struct

require 'dry-struct'
class OrderInput < Dry::Struct
  attribute :order_id, Types::String
  attribute :amount, Types::Coercible::Decimal
end

TypedPayload.typed_class?(OrderInput)  # => true
TypedPayload.to_h(OrderInput.new(order_id: '123', amount: 99.99))
# => { order_id: '123', amount: 99.99 }

with Data class

OrderInput = Data.define(:order_id, :amount)
TypedPayload.typed_class?(OrderInput)  # => true

Class Method Summary collapse

Class Method Details

.dry_struct_available?Boolean

Check if dry-struct is available

Returns:

  • (Boolean)


26
27
28
29
30
31
32
33
34
35
# File 'lib/shikibu/typed_payload.rb', line 26

def dry_struct_available?
  return @dry_struct_available if defined?(@dry_struct_available)

  @dry_struct_available = begin
    require 'dry-struct'
    true
  rescue LoadError
    false
  end
end

.from_array(array, element_type) ⇒ Array

Deserialize an array of typed objects

Parameters:

  • array (Array<Hash>)

    Array of hashes

  • element_type (Class)

    Element type class

Returns:

  • (Array)

    Array of typed instances



89
90
91
92
93
94
95
96
# File 'lib/shikibu/typed_payload.rb', line 89

def from_array(array, element_type)
  return array unless array.is_a?(Array)
  return array unless typed_class?(element_type)

  array.map do |item|
    item.is_a?(Hash) ? from_h(item, element_type) : item
  end
end

.from_h(hash, type_class) ⇒ Object

Deserialize a hash to a typed instance

Parameters:

  • hash (Hash)

    Hash to deserialize

  • type_class (Class)

    Target type class

Returns:

  • (Object)

    Typed instance or original hash



74
75
76
77
78
79
80
81
82
83
# File 'lib/shikibu/typed_payload.rb', line 74

def from_h(hash, type_class)
  return hash unless typed_class?(type_class)
  return hash unless hash.is_a?(Hash)

  # Symbolize keys for compatibility
  symbolized = deep_symbolize_keys(hash)

  # All typed classes support .new(**hash) interface
  type_class.new(**symbolized)
end

.to_h(obj) ⇒ Hash, Object

Serialize a typed instance to a hash

Parameters:

  • obj (Object)

    Typed instance or any object

Returns:

  • (Hash, Object)

    Serialized hash or original object



66
67
68
# File 'lib/shikibu/typed_payload.rb', line 66

def to_h(obj)
  deep_serialize(obj)
end

.typed_class?(obj) ⇒ Boolean

Check if an object is a typed payload class (not instance)

Parameters:

  • obj (Object)

    Object to check

Returns:

  • (Boolean)


40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/shikibu/typed_payload.rb', line 40

def typed_class?(obj)
  return false unless obj.is_a?(Class)

  # Check for dry-struct
  return true if dry_struct_class?(obj)

  # Check for Ruby 3.2+ Data class
  return true if data_class?(obj)

  # Check for duck-typed class with required methods
  duck_typed_class?(obj)
end

.typed_instance?(obj) ⇒ Boolean

Check if an object is a typed payload instance

Parameters:

  • obj (Object)

    Object to check

Returns:

  • (Boolean)


56
57
58
59
60
61
# File 'lib/shikibu/typed_payload.rb', line 56

def typed_instance?(obj)
  return true if dry_struct_instance?(obj)
  return true if data_instance?(obj)

  duck_typed_instance?(obj)
end