Skip to content

Type Refinement Traits

Alex Woods edited this page Mar 30, 2022 · 15 revisions

This wiki contains a mapping between Smithy Type refinement traits and generated Ruby code.

box Trait

Indicates that a shape is boxed. When a structure member is marked with this trait or the shape targeted by a structure member is marked with the box trait, the member may or may not contain a value, and the member has no default value. Boolean, byte, short, integer, long, float, and double shapes are only considered boxed if they are marked with the box trait. All other shapes are always considered boxed. There are changes expected in Smithy IDL 2.0, see: Default Zero Values Design. The smithy-ruby implementation of unboxed types should be compatible with the new @default trait.

structure MyType {
    @box
    integer BoxedInteger

    integer DefaultInteger
    
    boolean DefaultBool
}

Default values are set in the Type by overriding the initialize method:

MyType = ::Struct.new(
  :boxed_integer,
  :default_integer,
  :default_bool) do
  include Hearth::Structure

  def initialize(*)
    super
    self.default_bool ||= false
    self.default_number ||= 0
  end
end

error Trait

Indicates that a structure shape represents an error. Structures marked with this trait have a type definition, an error class, and a parser to populate the error structure.

@error("client")
structure ThrottlingError {}

The generated code is:

# types.rb
ThrottlingError = Struct.new(
  keyword_init: true
)

# errors.rb
class ThrottlingError < ApiClientError
  def initialize(http_resp:, **kwargs)
    @data = Parsers::ThrottlingError.parse(http_resp)
    kwargs[:message] = @data.message if @data.respond_to?(:message)
    super(http_resp: http_resp, **kwargs)
  end

  # @return [Types::ThrottlingError]
  attr_reader :data
end

# parsers.rb
class ThrottlingError
  def self.parse(http_resp)
    json = Hearth::JSON.load(http_resp.body)
    data = Types::ThrottlingError.new
    data
  end
end

The Hearth error parser determines that the response has an error, and delegates to the error class in errors.rb. Then the error’s class uses the parser in parsers.rb to populate a structure defined in types.rb. Depending on the value passed to the @error trait, the error will inherit from ApiClientError or ApiServerError. Read more on Errors and Error Parsing.

input Trait

Specializes a structure for use only as the input of a single operation. The input trait is useful for modeling but is not used during SDK code generation.

output Trait

Specializes a structure for use only as the output of a single operation. The output trait is useful for modeling but is not used during SDK code generation.

sparse Trait

Indicates that lists and maps MAY contain null values. The protocol’s null values are represented by Ruby’s nil value. For shapes without this trait, depending on the protocol, nil values are omitted when building or parsing the list element or map value. For example, check if unless element.nil? or unless value.nil? before populating the data structure.

@sparse
list SparseList {
    member: String
}

@sparse
map SparseMap {
    key: String,
    value: String
}

The generated code is:

# parsers.rb

class SparseList
  def self.parse(list)
    data = []
    list.each do |element|
      data << element # unless element.nil?
    end
    data
  end
end

class SparseMap
  def self.parse(map)
    data = {}
    map.each do |key, value|
      data[key] = value # unless value.nil?
    end
    data
  end
end

This works similarly for protocol builders.