Hello.
I’m working on a Ruby gem. Especially its specs.
We have custom Dry::Types
types. And we’re getting parsed API types for specs.
Attributes of our Ruby types have internal defaults, which external API has no.
How can I remove defaults from them?
Example:
class ReplyKeyboardRemove < Base
attribute? :selective, Types::Bool.default(false)
end
Error:
expected: #<Dry::Types[Sum<Constrained<Nominal<TrueClass> rule=[type?(TrueClass)]> | Constrained<Nominal<FalseClass> rule=[type?(FalseClass)]>>]>
got: #<Dry::Types[Default<Sum<Constrained<Nominal<TrueClass> rule=[type?(TrueClass)]> | Constrained<Nominal<FalseClass> rule=[type?(FalseClass)]>> value=false>]>
(compared using ==)
So I haven’t had to do this myself before, but one thing that’s with noting here is that a type with a default is just a wrapper over the original type, which you can still get to via my_type.type
.
So something like this becomes possible:
Undefined = Dry::Core::Constants::Undefined
t = Types::Bool.default(true)
# Show the default in action
t[Undefined]
# => true
# Get the raw (non-defaulting) type
tt = t.type
# Show it no longer has a default
tt[Undefined]
# This errors as expected!
# => Undefined violates constraints (type?(FalseClass, Undefined) failed) (Dry::Types::ConstraintError)
# And of course it still accepts a valid value
tt[false]
# => false
You’ll probably want to be careful with how you construct your types to make sure it’s actually the Default
wrapper that you’re unwrapping, but hopefully this can set you off in a good direction.
1 Like
Yeah, thanks, I’ve already found this work-around yesterday. attribute.type.type
seems weird, but works. I thought maybe there is a more elegant way. OK.
About safety — yeah, just if type.default?
enough.