Open solnic opened 4 years ago
@solnic shouldn't the rule be without .each
?
rule("contacts[].email") do
key.failure("email not valid") unless value.include?('@')
end
rule("contacts[].emails").each do
key.failure("email not valid") unless value.include?('@')
end
@skryukov I think it should be with each
, because otherwise we'd have to infer each
from the path anyway. I prefer to keep it explicit.
@solnic I see your point, but how we will differentiate, should we iterate over emails
or use email
as a target item for the rule? Maybe we should introduce another method to explicitly tell dry-v to find array items inside a rule?
@skryukov wait, I think I’m missing something - differentiate what?
@solnic I'll try to explain =)
For example, we have a schema like this:
require 'dry-validation'
class PropsContract < Dry::Validation::Contract
json do
required(:contacts).value(:array, min_size?: 1).each do
hash do
required(:name).filled(:string)
required(:email).filled(:string)
required(:phone).filled(:string)
required(:additional_emails).each(:string)
end
end
end
rule("contacts[].email").each do
key.failure("email not valid") unless value.include?('@')
end
rule("contacts[].additional_emails").each do
key.failure("email not valid") unless value.include?('@')
end
end
c = PropsContract.new
c.(
contacts: [
{ name: 'Jane', email: 'jane@doe.org', phone: '123', additional_emails: ['oops'] },
{ name: 'John', email: 'oops', phone: '123', additional_emails: ['jane@doe.org'] }
]).errors.to_h.inspect
# => {:contacts =>{0=>{:additional_emails =>{0=>["email not valid"]}}},1=>{:email=>["email not valid"]}}
So how should we know when a rule needs to be applied to the item itself (email
) and when on elements of the item (additional_emails
)? And what if I want to check something like this:
rule("contacts[].additional_emails").each(index:) do # or maybe even indexes in this case? =)
key.failure("additional emails contain primary email") if value.include?(values[:contacts][index][:email])
end
One more thing, contacts[].values[]
<- how would that work? :) It's probably better to reject such paths
I don't know. Please feel free to figure it out however you think is best 😄
Hello, I think my question suits this issue as well
I have a macro:
register_macro(:numeric_string?) do
condition = /^(\d)+$/.match?(value)
message = 'must be a numeric string'
key(keys.flatten).failure(message) unless condition
end
and I have to check in the same file both a single case such as the following:
rule(%i[data attributes token]).validate(:numeric_string?)
and for a separate case also array of numeric strings:
rule(%i[data attributes atrray_of_strings]).each do |r|
r.validate(:numeric_string?)
end
the last one does not work
is there a right way how to do that? if not, might be it should be added to the next versions?
Many thanks in advance
@TimoMoss for now you need to handle it manually, well implement a nice DSL for it at some point. For now I'm adding this to 1.7.0 milestone.
Examples
Resources
Refs #603