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


Default Values

A type with a default value will return the configured value when the input is not defined:

PostStatus = Types::String.default('draft')

PostStatus[] # "draft"
PostStatus["published"] # "published"
PostStatus[true] # raises ConstraintError

It works with a callable value:

CallableDateTime = Types::DateTime.default { DateTime.now }

CallableDateTime[]
# => #<DateTime: 2017-05-06T00:43:06+03:00 ((2457879j,78186s,649279000n),+10800s,2299161j)>
CallableDateTime[]
# => #<DateTime: 2017-05-06T00:43:07+03:00 ((2457879j,78187s,635494000n),+10800s,2299161j)>

Dry::Types::Undefined can be passed explicitly as a missing value:

PostStatus = Types::String.default('draft')

PostStatus[Dry::Types::Undefined] # "draft"

It also receives the type constructor as an argument:

CallableDateTime = Types::DateTime.constructor(&:to_datetime).default { |type| type[Time.now] }

CallableDateTime[Time.now]
# => #<DateTime: 2017-05-06T01:13:06+03:00 ((2457879j,79986s,63464000n),+10800s,2299161j)>
CallableDateTime[Date.today]
# => #<DateTime: 2017-05-06T00:00:00+00:00 ((2457880j,0s,0n),+0s,2299161j)>
CallableDateTime[]
# => #<DateTime: 2017-05-06T01:13:06+03:00 ((2457879j,79986s,63503000n),+10800s,2299161j)>

Be careful: types will return the same instance of the default value every time. This may cause problems if you mutate the returned value after receiving it:

default_0 = PostStatus.()
# => "draft"
default_1 = PostStatus.()
# => "draft"

# Both variables point to the same string:
default_0.object_id == default_1.object_id
# => true

# Mutating the string will change the default value of type:
default_0 << '_mutated'
PostStatus.(nil)
# => "draft_mutated" # not "draft"

You can guard against these kind of errors by calling freeze when setting the default:

PostStatus = Types::Params::String.default('draft'.freeze)
default = PostStatus.()
default << 'attempt to mutate default'
# => RuntimeError: can't modify frozen string

# If you really want to mutate it, call `dup` on it first:
default = default.dup
default << "this time it'll work"

Warning on using with constrained types: If the value passed to the .default block does not match the type constraints, this will not throw an exception, because it is not passed to the constructor and will be used as is.

CallableDateTime = Types::DateTime.constructor(&:to_datetime).default { Time.now }

CallableDateTime[Time.now]
# => #<DateTime: 2017-05-06T00:50:09+03:00 ((2457879j,78609s,839588000n),+10800s,2299161j)>
CallableDateTime[Date.today]
# => #<DateTime: 2017-05-06T00:00:00+00:00 ((2457880j,0s,0n),+0s,2299161j)>
CallableDateTime[]
# => 2017-05-06 00:50:15 +0300