mutations
mutations copied to clipboard
Feature request: `either_of` filter
I need an either_of
filter. It should accept a hash of values where exactly one key of the listed if filled:
either_of do
hash :a do
string :f1
end
hash :b do
string :f2
string :f3
end
hash :c do
string :f4
string :f5
end
end
Valid:
-
{"a": { "f1": "qwe" }}
-
{"b": { "f2": "qwe", "f3": "wqe" }}
-
{"c": { "f4": "asd", "f5": "asd }}
Error:
-
{}
-
{"a": { "f1": "qwe" }, "b": { "f2": "qwe", "f3": "wqe" }}
-
{ "d": {} }
-
{ "a": { "f1": "qwe" }, "d": "qwe" }
What do you think?
This seems like it would be a lot of work to implement, in order to satisfy a very specific use case.
It would be much easier, if a little uglier, to achieve this as a custom validation instead:
def validate
unless (raw_inputs.keys & %w(a b c)).one?
add_error(...)
end
end
If you did still want to work on this feature, I think I'd prefer to see a combination of two options:
any_of { ... }
, which uses the first filter that matches the input
strict: true
, which tells a hash filter to treat unexpected inputs as an error
I'm interested in any_of
because it could also be useful for arrays:
array :strings_and_numbers do
any_of do
string
integer
end
end
I ended up with the following:
hash :value do
optional do
hash :a do
string :f1
end
hash :b do
string :f2
string :f3
end
hash :c do
string :f4
string :f5
end
end
end
And a validator:
add_error(...) unless value.count == 1
And an accessor:
discriminant, data = value.first
It does the trick
I model algebraic enum, so it doesn't make sense to allow specifying nov value directly (as that would not provide the discriminant, which is mandatory). Instead, to allow nil
I'd do something like this:
optional do
hash :value do
optional do
string :a
integer :b
end
end
end
I'd still like to have an either_of
, though a bit different now.
either_of :value do
hash :a do
string :f1
end
hash :b do
string :f2
string :f3
end
hash :c do
string :f4
string :f5
end
end
Notice how there's :value
specified now.
If should also be usable with arrays:
array :strings_and_numbers do
either_of do
string :a
integer :b
end
end
array :strings_and_numbers do
optional do
either_of do
string :a
integer :b
end
end
end
Seems like I'll be using these quite a lot, and I'm a bit tired of using custom validators.