File: default-values.html.md

package info (click to toggle)
ruby-dry-types 1.2.2-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 504 kB
  • sloc: ruby: 3,059; makefile: 4
file content (91 lines) | stat: -rw-r--r-- 2,800 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
---
title: Default Values
layout: gem-single
name: dry-types
---

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

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

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

It works with a callable value:

``` ruby
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:

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

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

It also receives the type constructor as an argument:

```ruby
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:

```ruby
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:

```ruby
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.

```ruby
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
```