3

I would like to have an endpoint that validates against multiple schemas. I've read the docs and some of Eve's code but it's not immediately clear to me that this is possible. Here's a simple example of what I'd like to be able to do:

POST http://eve-server/vehicles/
{
    type: 'Boat',
    manufacturer: 'Seadoo',
    propeller_size: 2.0
}

POST http://eve-server/vehicles/
{
    type: 'Airplane',
    manufacturer: 'Boeing',
    wing_span: 195.8
}

GET http://eve-server/vehicles/

[
    {type: 'Boat', manufacturer: 'Seadoo', propeller_size: 2.0},
    {type: 'Airplane', manufacturer: 'Boeing', wing_span: 195.8}
]

Does Eve/Cerberus support polymorphic types like this? If not, is it possible to plug in something like JSON Schema that supports this while maintaining referential integrity that data_relation provides?

pmdarrow
  • 734
  • 5
  • 14

1 Answers1

1

Hmm I am not sure I understand your question. At first glance I'd say that's exactly how a normal API endpoint behaves. I'm assumingpropeller_size and wing_span are optional fields. You can post one document at a time like in your example:

POST http://eve-server/vehicles/
{
    type: 'Boat',
    manufacturer: 'Seadoo',
    propeller_size: 2.0
}

POST http://eve-server/vehicles/
{
    type: 'Airplane',
    manufacturer: 'Boeing',
    wing_span: 195.8
}

or you can post a list of documents:

POST http://eve-server/vehicles/    
[
    {type: 'Boat', manufacturer: 'Seadoo', propeller_size: 2.0},
    {type: 'Airplane', manufacturer: 'Boeing', wing_span: 195.8}
]

In both cases when you GET at the same endpoint you are going to get a list of available documents:

GET http://eve-server/vehicles/    
{
    "_items": [
        {type: 'Boat', manufacturer: 'Seadoo', propeller_size: 2.0},
        {type: 'Airplane', manufacturer: 'Boeing', wing_span: 195.8}
    ]
    "_meta": {
        "total": 259,
        "page": 1,
        "size": 25
    }
}

That's assuming HATEOAS has been disabled otherwise you're also going to get a _links meta field.

This being said, just keep in mind that you can setup multiple endpoints all targeting the same datasource, so you could have a POST-only endpoint with its own schema and validation and maybe a GET-only endpoint with a different schema, maybe because at thus endpoint you're returning fields which have been added via mongo, or event hooks (callbacks), or via other API endpoints.

Nicola Iarocci
  • 6,606
  • 1
  • 20
  • 33
  • You say mark `wing_span` and `propellor size` as optional fields. What if I want `wing_span` to be required when `type == Airplane` but not when `type == Boat`? Do I need to have custom validation somewhere that says `if type == 'foo', then 'bar' is required, elif type == 'baz' then 'qux' is required` or is there a cleaner way of doing this? – pmdarrow Nov 17 '14 at 20:38
  • Assume `wing_span` and `propellor_size` are mutually exclusive fields, that is `wing_span` is only allowed when `type == Airplane` and `propellor_size` is only allowed when `type == Boat`. In object oriented programming terms, I want `Vehicle` to be the base type and for `Boat` and `Airplane` to inherit from this base type, sharing common properties and common validation but each having properties and validation of their own. – pmdarrow Nov 17 '14 at 20:48
  • 1
    There's the `dependencies` validation rule for that, although right now it does not support field values. There's currently a pull request addressing your specific need so expect it to be supported soon. For reference: https://github.com/nicolaiarocci/cerberus/pull/61 – Nicola Iarocci Nov 18 '14 at 08:36
  • Actually, support for `dependencies` values has just been merged. – Nicola Iarocci Nov 18 '14 at 10:34
  • I suppose `dependencies` would work, I guess I was hoping for something a little more object-oriented. I'll post a separate question about swapping out Cerberus with another validation library. – pmdarrow Nov 18 '14 at 19:48