-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
field.rb
98 lines (80 loc) · 2.44 KB
/
field.rb
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
92
93
94
95
96
97
98
# typed: strict
module Typed
class Field
extend T::Sig
InlineSerializer = T.type_alias { T.proc.params(arg0: T.untyped).returns(T.untyped) }
sig { returns(Symbol) }
attr_reader :name
sig { returns(T::Types::Base) }
attr_reader :type
sig { returns(T.untyped) }
attr_reader :default
sig { returns(T::Boolean) }
attr_reader :required
sig { returns(T.nilable(InlineSerializer)) }
attr_reader :inline_serializer
sig do
params(
name: Symbol,
type: T.any(T::Class[T.anything], T::Types::Base),
optional: T::Boolean,
default: T.untyped,
inline_serializer: T.nilable(InlineSerializer)
).void
end
def initialize(name:, type:, optional: false, default: nil, inline_serializer: nil)
@name = name
# TODO: Guarentee type signature of the serializer will be valid
@inline_serializer = inline_serializer
coerced_type = T::Utils.coerce(type)
if coerced_type.valid?(nil)
@required = T.let(false, T::Boolean)
@type = T.let(T.unsafe(coerced_type).unwrap_nilable, T::Types::Base)
else
@required = true
@type = coerced_type
end
if optional
@required = false
end
if !default.nil? && @type.valid?(default)
@default = T.let(default, T.untyped)
@required = false
elsif !default.nil? && @required
raise ArgumentError, "Given #{default} with class of #{default.class} for default, invalid with type #{@type}"
end
end
sig { params(other: Field).returns(T.nilable(T::Boolean)) }
def ==(other)
name == other.name &&
type == other.type &&
required == other.required &&
default == other.default &&
inline_serializer == other.inline_serializer
end
sig { returns(T::Boolean) }
def required?
required
end
sig { returns(T::Boolean) }
def optional?
!required
end
sig { params(value: Value).returns(Value) }
def serialize(value)
if inline_serializer && value
T.must(inline_serializer).call(value)
else
value
end
end
sig { params(value: Value).returns(Validations::ValidationResult) }
def validate(value)
Validations::FieldTypeValidator.new.validate(field: self, value: value)
end
sig { params(value: Value).returns(T::Boolean) }
def works_with?(value)
type.recursively_valid?(value)
end
end
end