required(:answer).maybe seems to check answer is nil, or filled.
It disallows blank…
I was a bit tripped up over this.
Is it by design?
required(:answer).maybe seems to check answer is nil, or filled.
It disallows blank…
I was a bit tripped up over this.
Is it by design?
I does allow blank strings when you use Schema.Form
, or use a type which coerces empty strings to nils. I deliberately did it like that to remove implicit behaviors because there’s no place for implicit behaviors when it comes to coercion and validation. This is documented btw, but I guess it’s not visible enough in the docs.
I guess I had trouble trying to boil down my problem to a sensible question! Yes I understand about Form, which I’m using…
Can you help explain this array handling?
[8] pry(main)> s = Dry::Validation.Form { required(:options).maybe }; nil
=> nil
[9] pry(main)> s.(options: [])
=> #<Dry::Validation::Result output={:options=>[]} errors={:options=>["must be filled"]}>
It allows (no error) with a blank string:
[10] pry(main)> s.(options: '')
=> #<Dry::Validation::Result output={:options=>nil} errors={}>
Or a filled in array:
[11] pry(main)> s.(options: ['one'])
=> #<Dry::Validation::Result output={:options=>["one"]} errors={}>
Or a nil (as expected with the maybe):
[12] pry(main)> s.(options: nil)
=> #<Dry::Validation::Result output={:options=>nil} errors={}>
I can get around it with:
s = Dry::Validation.Form { required(:options) { filled? | empty? } }
but it seems like the fact it’s a “Form” should allow the empty Array?
Also found specifying the type allows empty array:
Dry::Validation.Form { require(:options).maybe(:array?) }
My problem is really that I don’t want any validation on “options” except when inside a custom rule.
However, if i do this:
[37] pry(main)> s = Dry::Validation.Form { required(:options) }; nil
=> nil
[38] pry(main)> s.({}).success?
=> true
Then it doesn’t seem to be verifying anything… which would be ok, but! I see that my higher level rule doesn’t fire as if the :options rule didn’t fire. Here’s the actual rule I have:
rule(answer: [:answer, :kind, :optional, :options]) do |answer, kind, optional, options|
(optional.false? > answer.filled?) &
((answer.filled? & kind.eql?('number')) > answer.number?) &
# Only in this "then" do I want to validation options is filled
((answer.filled? & kind.eql?('options')) > (
options.filled? & answer.included_in?(value(:options))
))
end
Can you help explain this array handling?
It works like that because maybe
is for accepting nils, we probably should not add special cases depending on a schema type as this would only make things more complicated. If you have a case where an empty can be passed in, just use required(:options).value(:array?)
.
Also found specifying the type allows empty array
Yes, because the way you specify it means it can be nil or an array (doesn’t matter if filled or not).
s = Dry::Validation.Form { required(:options) }
This doesn’t work, you need to specify rules for the value too. It’ll be improved in 1.0.0.
This cleared it up for me:
It shows that if you use “required(:options).maybe” then you are in fact using a ‘default’ right-hand side of :filled?. That means the maybe is saying:
"You can have null, or if you give a value, it must be filled".
That’s the thing that tripped me up I reported originally! It’s a bit more confusing since the default ‘filled?’ is just that – it’s removed if you provide anything else, like “required(:options).maybe(:array?)”.
I think you were explaining things perfectly, but it didn’t reach me – maybe I didn’t get clear on how the ‘filled?’ was coming into play.
This would be good to have in the docs. I’ll try and send a PR later.