Services & Skills

Share on

The structure is like dry-struct, except it controls optional attributes and default values aside of type constraints.

Its DSL is taken from dry-initializer. Its method attribute is just an alias for option.

require "evil-struct"
require "dry-types"

class Product < Evil::Struct
  attribute :title
  attribute :price,    Dry::Types["coercible.float"]
  attribute :quantity, Dry::Types["coercible.int"], default: proc { 0 }

  # shared options
  attributes optional: true do
    attribute :subtitle
    attribute :description

# Accepts both symbolic and string keys.
# Class methods `[]`, `call`, and `load` are just aliases for `new`
product = Product[title: "apple", "price" => "10.9", description: "a fruit"]

# Attributes are available via methods or `[]`
product.title       # => "apple"
product[:price]     # => 10.9
product["quantity"] # => 0
product.description # => "a fruit"

# unassigned value differs from `nil`
product.subtitle    # => Dry::Initializer::UNDEFINED

# Raises in case a mandatory value was not assigned
Product.new # BOOM! because neither title, nor price are assigned

# Hashifies all attributes except for undefined subtitle
# You can use `dump` as an alias for `to_h`
# => { title: "apple", price: 10.9, description: "a fruit", quantity: 0 }

# The structure is comparable to any object that responds to `#to_h`
product == { title: "apple", price: 10.9, description: "a fruit", quantity: 0 }
# => true

In the same orbit

Explore more open source projects

How can we help you?

Martians at a glance
years in business

We transform growth-stage startups into unicorns, build developer tools, and create open source products.

If you prefer email, write to us at surrender@evilmartians.com