tmpfs / async-validate

Asynchronous type validation for node and the browser
Other
314 stars 45 forks source link

is support for ruleset X or ruleset Y supported? #56

Closed 0xgeert closed 8 years ago

0xgeert commented 8 years ago

Async-validate seems great at first glance: Everything seems to be supported for my validation purposes (or otherwise I can extend it). However, I couldn't find 1 low-level 'validation routing primitive' for lack of a better word:

usecase: want to build validation for schema.org entities

some schema.org properties, such as performer allow the value to be polymorphic. In the example of performer a value can either be a Person or an MusicGroup.

The JSON-LD way to mark this up is to specify the type as a @type param. So an object fragment displaying the performer could be:

....
 "performer": 
    {
      "@type": "MusicGroup",
      "name": "Chicago Symphony Orchestra",
      "brand": "property specific to type=MusicGroup"
    }

Or it could be:

  "performer": 
    {
      "@type": "Person",
       "name": "some name",
      firstName:  "property specific to type=Person"
    }

Or it could even be:

  ...
  "performer": [
    {
      "@type": "MusicGroup",
      "name": "Chicago Symphony Orchestra",
      "brand": "property specific to type=MusicGroup"
    },
    {
      "@type": "Person",
       "name": "some name",
      firstName:  "property specific to type=Person"
    }
  ],

Logically, Person would have different validation rules than Organization. What I'd like to find a solution to is to be able to define a ruleset for both Organization and Person and select the proper ruleset based on some condition, here: the value of @type

Is this supported currently, and if not would you consider a pull request? If the latter, any pointers on where best to start digging?

Related: when defining an array of objects, is there a way to define the type of the items inside the arrays? I.e: type=array + items="Object", or in the above example type=array + items=[Person,Organization] might make sense for instance

tmpfs commented 8 years ago

Thanks for the issue.

You can of course define a custom rule that would do this for your purpose, let's work together to find the best way to implement this for your use-case.

I am resting until the 10th, I'll be in touch again afterwards.

FYI:

Related: when defining an array of objects, is there a way to define the type of the items inside the arrays? I.e: type=array + items="Object", or in the above example type=array + items=[Person,Organization] might make sense for instance

Should be resolved with:

https://github.com/freeformsystems/async-validate/issues/46 https://github.com/freeformsystems/async-validate/commit/6db76c43d196ea399c52b9062e9cbf2736d86088

You should be able to find a test case for this - let me know if there isn't one!

tmpfs commented 8 years ago

Here is my current thinking, we define a rule property such as resolve which points to a function that inspects the object being processed and returns the rule to execute for that object. The function would be called synchronously and must return a valid rule, for example:

var Person = // define rule for person
var MusicGroup = // define rule for music group
function resolve() {
  switch(this['@type']) {  // called with `this` as the object being validated
    case "Person":
      return Person;
    case "MusicGroup":
      return MusicGroup;
  }
  throw new Error('Unknown @type encountered')
}

Then in the rule declaration assign the resolve() function to the resolve property which would be executed to locate the rule.

How does that sound?

0xgeert commented 8 years ago

Yep sounds good to me.

FYI: moved on by doing some custom hacking in schema.js that let's me circumvent the issue since I needed some other stuff as well, but this certainly seems to solve this particular issue pretty elegantly.

On Fri, Jan 8, 2016 at 12:00 PM, muji notifications@github.com wrote:

Here is my current thinking, we define a rule property such as resolve which points to a function that inspects the object being processed and returns the rule to execute for that object. The function would be called synchronously and must return a valid rule, for example:

var Person = // define rule for personvar MusicGroup = // define rule for music groupfunction resolve() { switch(this['@type']) { // called with this as the object being validated case "Person": return Person; case "MusicGroup": return MusicGroup; } throw new Error('Unknown @type encountered') }

Then in the rule declaration assign the resolve() function to the resolve property which would be executed to locate the rule.

How does that sound?

— Reply to this email directly or view it on GitHub https://github.com/tmpfs/async-validate/issues/56#issuecomment-169964014 .

tmpfs commented 8 years ago

This has been implemented in ef53cae7da2d9d584cc615786c6bf14a20744b9e.

Added to the readme here:

https://github.com/tmpfs/async-validate#resolve

Test spec is here:

https://github.com/tmpfs/async-validate/blob/master/test/spec/resolve.js

Published to the registry as 0.12.4.

I have found a bug noted here #57 which may or may not be related to the resolve implementation, I have a feeling this is a wider issue to do with handling arrays at the top-level, will investigate later.

For the moment I am closing this particular issue as implemented - hope it helps!

0xgeert commented 8 years ago

cheers!

On Tue, Jan 12, 2016 at 7:02 AM, muji notifications@github.com wrote:

Closed #56 https://github.com/tmpfs/async-validate/issues/56.

— Reply to this email directly or view it on GitHub https://github.com/tmpfs/async-validate/issues/56#event-512015788.