These are chat archives for dry-rb/chat

5th
Jun 2018
ojab
@ojab
Jun 05 2018 15:26
type = Dry::Types['params.time'].constrained({}).optional
type[Dry::Types::Undefined]
# => Undefined violates constraints (Undefined must be an instance of Time failed) (Dry::Types::ConstraintError)
unconstrained type works fine, is it expected behaviour?
type[nil] doesn't raise, btw
Nikita Shilnikov
@flash-gordon
Jun 05 2018 15:57
why do you pass Undefined to optional?
optional has no default value, it's just strict.nil | whatever
ojab
@ojab
Jun 05 2018 16:03
I'm parsing stuff in constructor and I want to provide a value that will pass .optional and set default value, if exist. So AFAIU if I'll pass nil there will not be default value.
*default value in dry-struct that is used on upper level
ojab
@ojab
Jun 05 2018 16:30
and looks like my issue is a result of messing with dry-struct constructor
ojab
@ojab
Jun 05 2018 16:51
kinda reduced testcase:
type = Dry::Types['params.time'].constrained(
  gteq: ::Time.parse('1753-01-01 12:00:00')
)
type = type.constructor do |input|
  input.respond_to?(:to_time) ? input.to_time : input
end

TYPE = type.optional.meta(omittable: true)

User = Dry.Struct do
  attribute :time, type
end

p User.new(time: nil)
# => [User.new] nil (NilClass) has invalid type for :time violates constraints (nil must be an instance of Time failed) (Dry::Struct::Error)
ouch, passing type instead of TYPE, wrong reduction
ojab
@ojab
Jun 05 2018 17:30
another question then:
struct = Dry.Struct do
  attribute :time, Dry::Types['string']
end

struct = struct.constructor { |input| input }

struct.optional
# => undefined method `optional' for #<Dry::Struct::Constructor type=#<Class:0x000000000175bf10>> (NoMethodError)
dry-s should quack as dry-t, so this should work in theory?
ojab
@ojab
Jun 05 2018 17:38
and why coercion constructor runs before custom one?
hash = Dry::Types['hash'].constructor { |input| { x: 1 } }
coercible = Dry::Types['coercible.hash'].constructor { |input| { x: 1 } }

p hash['foo'] # => { x: 1 }
p coercible['foo'] # => can't convert String into Hash (TypeError)
Nikita Shilnikov
@flash-gordon
Jun 05 2018 17:47
and why not? It's ordinary function composition
we'll likely add option for alternative composition though before 1.0 is out
ojab
@ojab
Jun 05 2018 17:48
yeah, but I'm expecting that latter constructors will run before existing ones
hash = Dry::Types['hash'].constructor { |input| { x: 1 } }
                         .constructor { |input| { y: 2 } }
p hash['foo'] # => { y: 2 }
hmm, so I will receive input from existing constructors
Nikita Shilnikov
@flash-gordon
Jun 05 2018 17:51
I think people may have different opinions on the matter, as in, function composition is usually defined as f . g = \x -> f(g(x)) (read "f after g")
but there's nothing wrong with the opposite order
it's just we need to come up with some API
will add a flag probably