tomdalling / rschema

Schema-based validation and coercion for Ruby data structures

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for Mutually Exclusive Keys in Hashes

bbbco opened this issue · comments

I'd like to be able to define keys within a hash that are mutually exclusive (i.e., only one of them should exist).

# Good
{
  "foo": "bar"
}

# Good
{ 
  "fu": "ba"
}

# Bad
{
  "foo": "bar",
  "fu": "ba"
}

Maybe it could look like something like:

RSchema.define({
  exclusive("foo", :with => "fu") => type(_String),
  exclusive("fu", :with => "foo") => type(_String)
})

There are a couple of ways to do this currently (in RSchema v3).

If those are the only keys in the hash, you can just use either:

RSchema.define do
  either(Hash('foo' => _String), Hash('fu' => _String))
end

If there are other keys in the hash, you can use two separate schemas:

BAZ_FU = RSchema.define_hash {{ 
  'other_key' => _Integer,
  'fu' => _String,
}}
BAZ_FOO = RSchema.define do
  # this is new, currently undocumented syntax that might change
  Hash_based_on(BAZ_FU, {
    'fu' => nil, # removes 'fu' element
    'foo' => _String, #adds new 'foo' element
  })
end

BAZ = RSchema.define { either(BAZ_FU, BAZ_FOO) }

Trying to building this into the hash schema raises a few questions. What if there are 3 exclusive keys instead of 2? What if a hash should have either the single key "name", or both of the keys "first_name" and "last_name"? I'd like to come up with a design that addresses these questions. I'll need some time to think about it.