Hi Guys,
Thank you for sharing this great tool!
I have been struggling to validate a hash with an array of hashes which should be checked based on an option.
For instance, if the group
is a
, then, the content
attribute should be A
, and if b
, then B
.
This should be valid:
{ group: "a", list: [{content: "A"}, {content: "A"}] }
And this should not be valid (note the content of the last element of array is B
):
{ group: "a", list: [{content: "A"}, {content: "B"}] }
This is how I am think it should be implemented:
require 'rails_helper'
describe "Passing options along to nested array of hashes" do
let(:base_schema) do
Dry::Validation.Schema do
configure do
def self.messages
super.merge( en: { errors: { group?: "if group is %{group} then content cannot be %{content}" } } )
end
end
end
end
let(:list_schema) do
Dry::Validation.Schema(base_schema) do
configure do
option :group
def group?(group, content)
(group == "a" && content == "A") || (group == "b" && content == "B")
end
end
required(:content).filled(group?: group)
end
end
describe "ListSchema (THIS WORKS FINE)" do
context "Valid input" do
let(:subject) { list_schema.with(group: "a").call( content: "A" ) }
it { is_expected.to be_success }
end
context "Invalid input" do
let(:subject) { list_schema.with(group: "a").call( content: "B" ) }
it { expect(subject.messages).to eq( content: ["if group is a then content cannot be B"] ) }
end
end
describe "MainSchema (THIS DOES NOT WORK)" do
let(:main_schema) do
ListSchema ||= list_schema
Dry::Validation.Schema(base_schema) do
required(:group).value(included_in?: ["a", "b"])
required(:list).value(:array?)
rule list_for_group: [:list, :group] do |list, group|
group.included_in?(["a", "b"]) > list.each do
schema(ListSchema.with(group: group))
end
end
end
end
context "Valid input" do
let(:subject) { main_schema.call( group: "a", list: [{ content: "A" }, { content: "A" }] ) }
it { expect(subject).to be_success }
end
context "Invalid input" do
let(:subject) { main_schema.call( group: "a", list: [{ content: "A" }, { content: "B" }] ) }
it { expect(subject.messages).to eq( list: { 1 => { content: ["if group is a then content cannot be B"] } } ) }
end
end
end
I could not build a MainSchema
which makes the last to scenarios to pass. I guess the rule
is wrong.
Is there any way to achieve this?
Cheers,
Leandro