Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to build a complex schema when using with Rails #328

Closed
AlexVPopov opened this issue May 30, 2016 · 4 comments
Closed

How to build a complex schema when using with Rails #328

AlexVPopov opened this issue May 30, 2016 · 4 comments

Comments

@AlexVPopov
Copy link

I am using json-schema together with rspec to assert that responses from a rails api match certain schemas. I have used this article as a guiding example. The schemas are placed under spec/support/schemas . My question is - how can I reuse the schemas in one another. For example, let's say we have the schema for a Foo model in the file spec/support/schemas/foo.json:

{
  "type": "object",
  "required": ["some_key"],
  "properties": {...}
}

We would use this schema to assert the response from FoosController#show. If we want to assert that the response of FoosController#index is an array of foos, in spec/support/schemas/foos.json we would place something like:

{
  "type": "object",
  "required": ["foos"],
  "properties": {
    "foos": {
      "type": "array",
      "items": { ... }
      }
    }
  }
}

The value of the items key in foos.json should be the value of the properties key of foo.json.

I have read the relevant part of Understanding JSON Schema, but I am not sure how to do that in the context of Rails. How can I do that, without having to host my json schemas on a public domain, but make it work as some kind of a Rails asset, so that schemas are aware of the environment and refer to the particular host, where they are located (say localhost:3000, when in development mode, but some public domain, when the app is deployed).

Thank you very much for your answer.

@jblac
Copy link

jblac commented Jun 10, 2016

I had to do this exact thing, came to issues to check questions -- went to understanding json schema like you did. poked around a little bit and figured it out.

There are two ways you can do this

you can do it inside the same json file with a "definitions" key, which would work for certain things and is well documented on the website. Or you can require a different file, which is super simple. So, updating your example, where we have Foo which lists the Bar

bar.json:

{
  "type": "object",
  "required": ["some_key"],
  "properties": { ... }
}

and the foo.json:

{
  "type": "object",
  "required": ["bars"],
  "properties": {
    "bars": {
      "type": "array",
      "items": { "$ref": "bar.json" }
    }
  }
}

and there you go. Keep in mind there are benefits to using both versions, I'd really reserve the latter in the event that you need to reuse the specific schema configuration in multiple different places where it would require an awful amount of duplication.

Hope this is what you are asking for, it's not really clear fully.

@AlexVPopov
Copy link
Author

@jblac I am terribly sorry for the super late response. Thank you very much for your answer. So my question - how does $ref work - does it look for a file named bar.json in the current folder? Can I use it to specify relative paths, like "$ref": "../some_folder_name/bar.json"?

@RST-J
Copy link
Contributor

RST-J commented Aug 12, 2016

You seem to confuse what $ref is semantically used/meant for in the JSONschema standard and how json-schema resolves it. $ref may hold any valid JSON Pointer, which usually is in the form of a fragment '#definitions/address' as illustrated here or a full URI like 'https://schemas.example.com/some/path/schema.json'.
A file path also is a valid value.
However, think about that if you publish your schema for your users (e.g. as part of an API description) that a reference to '../shared/address' will not help them anything.

json-schema gives you free control over whether and how to load schemas from files and remote resources. You can also override the schema loading mechanism (we do that in our project to map remote URIs to locally cached schema files to avoid the additional roundtrips).

The basic answer is: File loading and remote resource loading are enabled by default. File references are resolved from the current folder (CWD I think), remote resources fetched via Rubys open.

@AlexVPopov
Copy link
Author

@RST-J, you are completely right, until I read your answer I was confused about how $ref works and I thank you for taking the time explaining it to me - herzlichen Dank. It seems that I will use an initializer for json-schema, where it'll read all the schema definitions under spec/support and then I'll use only file references. This is because:

  1. I'll only use locally defined schemas, I won't make any external calls.
  2. I don't have users in the classical sense, as I am only using json-schema in tests.

Once again, thanks a lot for the info!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants