Documentation
¶
Overview ¶
Package drystruct is a pure-Go (CGO-free) MRI-faithful reimplementation of the Ruby dry-struct gem: typed, immutable value objects whose attributes are coerced and validated by github.com/go-ruby-dry-types/dry-types types.
A *StructType is the analogue of a `Dry::Struct` subclass: you register attributes on it (each a name plus a dry-types drytypes.Type), then construct instances from an attribute hash. Construction coerces and validates every attribute through its type, and — on the first failure — raises a *Error whose message is byte-identical to the dry-struct gem's (`[Name.new] <schema error>`).
Ruby value model ¶
Attribute values use the same small Go value model the go-ruby-* ecosystem (and go-ruby-dry-types) uses, so a host (go-embedded-ruby / rbgo) maps its object graph to and from this package with no glue:
Ruby Go ---- -- nil nil true / false bool Integer int64, *big.Int Float float64 String string Symbol drytypes.Symbol Array []any Hash *drytypes.Map (ordered) Dry::Struct *Struct
A *Struct is one immutable instance: an ordered map of attribute name to coerced value, tagged with its *StructType. It answers the reader, Struct.ToH, Struct.With, Struct.Eql and Struct.Inspect operations the gem exposes.
Index ¶
- type AttrType
- type Attribute
- type Error
- type KeyTransform
- type Struct
- func (s *Struct) Attributes() *drytypes.Map
- func (s *Struct) Eql(other *Struct) bool
- func (s *Struct) Fetch(name drytypes.Symbol) any
- func (s *Struct) Get(name drytypes.Symbol) (any, bool)
- func (s *Struct) Inspect() string
- func (s *Struct) String() string
- func (s *Struct) ToH() *drytypes.Map
- func (s *Struct) ToHash() *drytypes.Map
- func (s *Struct) Type() *StructType
- func (s *Struct) With(changes *drytypes.Map) (*Struct, error)
- type StructType
- func (s *StructType) AsValue() *StructType
- func (s *StructType) Attribute(name drytypes.Symbol, t drytypes.Type) *StructType
- func (s *StructType) AttributeOpt(name drytypes.Symbol, t drytypes.Type) *StructType
- func (s *StructType) AttributeType(name drytypes.Symbol, t AttrType) *StructType
- func (s *StructType) AttributeTypeOpt(name drytypes.Symbol, t AttrType) *StructType
- func (s *StructType) Attributes() []Attribute
- func (s *StructType) Call(attrs any) (any, error)
- func (s *StructType) Coerce(v any) (any, error)
- func (s *StructType) Inherit(name string) *StructType
- func (s *StructType) IsValue() bool
- func (s *StructType) MustNew(attrs any) *Struct
- func (s *StructType) New(attrs any) (*Struct, error)
- func (s *StructType) Strict() *StructType
- func (s *StructType) TransformKeys(t KeyTransform) *StructType
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AttrType ¶
type AttrType interface {
// Coerce coerces and validates v, returning the coerced value or an error
// whose message matches the gem's.
Coerce(v any) (any, error)
}
AttrType is the type of an attribute: it coerces-and-validates the attribute's value. Both a dry-types drytypes.Type (via Wrap) and a nested *StructType satisfy it, which is how nested structs compose as attribute types without dry-types needing to know about structs.
func ArrayOf ¶
ArrayOf builds an AttrType for a member-typed array whose element type is any AttrType (a nested *StructType or a wrapped dry-types type). For a plain dry-types element you can also use drytypes.ArrayOf directly and pass the result to StructType.Attribute.
func Wrap ¶
Wrap adapts a dry-types drytypes.Type into an AttrType so it can be used as an attribute type. StructType.Attribute accepts a drytypes.Type directly and wraps it for you; this is exposed for callers building [Attribute]s by hand.
type Attribute ¶
type Attribute struct {
// Name is the attribute's symbol name (Ruby `:name`).
Name drytypes.Symbol
// Type coerces and validates the attribute's value.
Type AttrType
// Optional reports whether the attribute was declared with `attribute?`.
Optional bool
}
Attribute is one declared member of a *StructType: its symbol name, the AttrType (a dry-types type or a nested *StructType) that coerces-and- validates its value, and whether it is optional (declared with `attribute?`, i.e. the key may be absent).
type Error ¶
type Error struct {
// Message is the full, gem-faithful error message.
Message string
// Cause is the underlying dry-types error (schema / coercion / constraint /
// missing-key / unknown-keys) that this wraps.
Cause error
}
Error is raised when constructing a *Struct fails: an attribute is missing, an unexpected key is present under a strict schema, or an attribute's value fails its dry-types coercion/constraint. Its message is byte-identical to Dry::Struct::Error#message: the struct's failing-schema message prefixed with `[<Name>.new] ` (e.g. `[User.new] :age is missing in Hash input`).
type KeyTransform ¶
type KeyTransform int
KeyTransform names how a *StructType normalizes incoming hash keys before matching them to attributes (dry-struct's `transform_keys`).
const ( // KeyNone leaves keys unchanged (the default): keys are matched as given, // with a String key accepted for a Symbol attribute of the same name. KeyNone KeyTransform = iota // KeySymbolize maps every String key to a Symbol (`transform_keys(&:to_sym)`). KeySymbolize // KeyStringify maps every Symbol key to a String, then back to a Symbol for // matching (`transform_keys(&:to_s)`) — dry-struct still requires the // declared attribute name. KeyStringify )
type Struct ¶
type Struct struct {
// contains filtered or unexported fields
}
Struct is one immutable dry-struct instance: an ordered map from attribute name to coerced value, tagged with the *StructType that produced it. It answers the reader, Struct.ToH, Struct.With, Struct.Eql and Struct.Inspect operations the gem's instances expose.
func (*Struct) Attributes ¶
Attributes returns the instance's attributes as an ordered *drytypes.Map (Ruby `#attributes`), with nested *Struct values kept as-is (not deep converted — that is what Struct.ToH does). The returned map must not be mutated.
func (*Struct) Eql ¶
Eql reports whether two instances are equal (Ruby `#==` / `#eql?`): same *StructType and equal attribute maps. Structs of different types are never equal, matching the gem.
func (*Struct) Fetch ¶
Fetch returns the value of attribute name, or nil if it is absent — the direct analogue of Ruby's attribute reader / `struct[:name]`.
func (*Struct) Get ¶
Get returns the value of attribute name and whether it is present. An optional attribute that was absent at construction is not present (and reads back nil), matching the gem's `struct[:key]` returning nil for an unset optional.
func (*Struct) Inspect ¶
Inspect renders the instance the way dry-struct's `#inspect` does: `#<Name attr=<inspect> …>` in declaration order, with an absent optional attribute shown as `attr=nil`. An attribute-less struct renders `#<Name>`.
func (*Struct) String ¶
String is an alias for Struct.Inspect so a *Struct prints faithfully via fmt.
func (*Struct) ToH ¶
ToH deep-converts the instance to an ordered *drytypes.Map (Ruby `#to_h` / `#to_hash`): nested *Struct values become their own to_h, and arrays of structs map element-wise. Absent optional attributes are omitted.
func (*Struct) ToHash ¶
ToHash is an alias for Struct.ToH (Ruby exposes both `#to_h` and `#to_hash`).
func (*Struct) Type ¶
func (s *Struct) Type() *StructType
Type returns the *StructType this instance was built from.
type StructType ¶
type StructType struct {
// Name is the struct's class name, used in error messages and inspect
// (`[Name.new] …`, `#<Name …>`).
Name string
// contains filtered or unexported fields
}
StructType is the analogue of a `Dry::Struct` subclass: a named, ordered list of [Attribute]s plus its key-transform and strictness config. It is the factory for *Struct instances (via StructType.New / StructType.Call).
A StructType implements drytypes.Type, so it can itself be used as the type of an attribute on another StructType — that is how nested structs and `Types::Array.of(SomeStruct)` compose. Applying it to a hash coerces that hash into a *Struct; applying it to an existing *Struct of the same type passes it through unchanged (mirroring the gem).
func Define ¶
func Define(name string, build func(*StructType)) *StructType
Define is the `Dry.Struct do … end` DSL: it builds an anonymous *StructType named name and runs build against it to register attributes and config, returning the finished type. It is sugar over New + the chaining methods.
func New ¶
func New(name string) *StructType
New builds an empty *StructType with the given class name. Register attributes with StructType.Attribute / StructType.AttributeOpt (they return the receiver, so calls chain).
func (*StructType) AsValue ¶
func (s *StructType) AsValue() *StructType
AsValue marks the struct a `Dry::Struct::Value` (comparable-by-value; the gem also freezes it — every instance here is already immutable). Returns the receiver for chaining.
func (*StructType) Attribute ¶
func (s *StructType) Attribute(name drytypes.Symbol, t drytypes.Type) *StructType
Attribute declares a required attribute (`attribute :name, type`) whose type is a dry-types drytypes.Type, and returns the receiver for chaining. Re-declaring a name replaces it in place (keeping its position), matching a subclass overriding an inherited attribute.
func (*StructType) AttributeOpt ¶
func (s *StructType) AttributeOpt(name drytypes.Symbol, t drytypes.Type) *StructType
AttributeOpt declares an optional attribute (`attribute? :name, type`) whose type is a dry-types drytypes.Type: the key may be absent, in which case the attribute is omitted from Struct.ToH and reads back as nil. Returns the receiver for chaining.
func (*StructType) AttributeType ¶
func (s *StructType) AttributeType(name drytypes.Symbol, t AttrType) *StructType
AttributeType declares a required attribute whose type is any AttrType — a nested *StructType (for `attribute :address, AddressStruct`) or a wrapped dry-types type. Returns the receiver for chaining.
func (*StructType) AttributeTypeOpt ¶
func (s *StructType) AttributeTypeOpt(name drytypes.Symbol, t AttrType) *StructType
AttributeTypeOpt declares an optional attribute whose type is any AttrType. Returns the receiver for chaining.
func (*StructType) Attributes ¶
func (s *StructType) Attributes() []Attribute
Attributes returns the declared attributes in declaration order. The slice must not be mutated.
func (*StructType) Call ¶
func (s *StructType) Call(attrs any) (any, error)
Call is `Struct.call(attrs)` / `Struct[attrs]` — an alias for StructType.New.
func (*StructType) Coerce ¶
func (s *StructType) Coerce(v any) (any, error)
Coerce lets a *StructType serve as an attribute type (nested struct): it constructs the nested *Struct from v, returning the gem-shaped error on failure so the enclosing schema can wrap it.
func (*StructType) Inherit ¶
func (s *StructType) Inherit(name string) *StructType
Inherit returns a new *StructType named name that begins with a copy of the parent's attributes and config (dry-struct subclassing). Further StructType.Attribute calls append to (or override) the inherited set.
func (*StructType) IsValue ¶
func (s *StructType) IsValue() bool
IsValue reports whether the struct was declared a `Dry::Struct::Value`.
func (*StructType) MustNew ¶
func (s *StructType) MustNew(attrs any) *Struct
MustNew is StructType.New but panics on error; convenient for tests and for statically-known-valid construction.
func (*StructType) New ¶
func (s *StructType) New(attrs any) (*Struct, error)
New constructs a *Struct from an attribute hash, coercing and validating every attribute through its AttrType. It is `Struct.new(attrs)`:
- Each required attribute must be present (else `:key is missing in Hash input`); an optional attribute may be absent.
- Under a strict schema, unexpected keys raise `unexpected keys […]`.
- Each present value is coerced through its type; the first failure raises a *Error shaped like the gem's.
As a special case matching the gem, New(existing) where existing is already a *Struct of this exact type returns it unchanged (no re-coercion).
func (*StructType) Strict ¶
func (s *StructType) Strict() *StructType
Strict marks the struct's schema strict (`schema schema.strict`): construction rejects unexpected keys. Returns the receiver for chaining.
func (*StructType) TransformKeys ¶
func (s *StructType) TransformKeys(t KeyTransform) *StructType
TransformKeys sets the incoming-key normalization (dry-struct's `transform_keys`). Returns the receiver for chaining.
