dry-types

v1.8 v1.7
  1. Introduction
  2. Getting Started
  3. Built-in Types
  4. Type Attributes
  5. Default Values
  6. Fallbacks
  7. Constraints
  8. Hash Schemas
  9. Array With Member
  10. Enum
  11. Map
  12. Combining Types
    1. Intersection
    2. Sum
  13. Custom Types
  14. Custom Type Builders
  15. Extensions
    1. Maybe
    2. Monads

TOC

  1. Mappings

Enum

In many cases you may want to define an enum. For example, in a blog application a post may have a finite list of statuses. Apart from accessing the current status value, it is useful to have all possible values accessible too. Furthermore, an enum can be a map from, e.g., strings to integers. This is useful for mapping externally-provided integer values to human-readable strings without explicit conversions, see examples.

require 'dry-types'
require 'dry-struct'

module Types
  include Dry.Types()
end

class Post < Dry::Struct
  Statuses = Types::String.enum('draft', 'published', 'archived')

  attribute :title, Types::String
  attribute :body, Types::String
  attribute :status, Statuses
end

# enum values are frozen, let's be paranoid, doesn't hurt and have potential to
# eliminate silly bugs
Post::Statuses.values.frozen? # => true
Post::Statuses.values.all?(&:frozen?) # => true

Post::Statuses['draft'] # => "draft"

# it'll raise if something silly was passed in
Post::Statuses['something silly']
# => Dry::Types::ConstraintError: "something silly" violates constraints

# nil is considered as something silly too
Post::Statuses[nil]
# => Dry::Types::ConstraintError: nil violates constraints

Note that if you want to define an enum type with a default, you must call .default before calling .enum, not the other way around:

# this is the correct usage:
Dry::Types::String.default('red').enum('blue', 'green', 'red')

# this will raise an error:
Dry::Types::String.enum('blue', 'green', 'red').default('red')

Mappings

A classic example is mapping integers coming from somewhere (API/database/etc) to something more understandable:

class Cell < Dry::Struct
  attribute :state, Types::String.enum('locked' => 0, 'open' => 1)
end


Cell.new(state: 'locked')
# => #<Cell state="locked">

# Integers are accepted too
Cell.new(state: 0)
# => #<Cell state="locked">
Cell.new(state: 1)
# => #<Cell state="open">