Reality check your library idea

Thanks for the feedback! I really like the aliasing, definitely something I’ll consider!

The example I chose probably wasn’t ideal but your feedback definitely helped with pushing the API in a better direction. The idea behind adapter and resolver is a distinct separation between “validation” and “schema loading” (see below for details on what that means).

In my current iteration you (could) now use them like this (name is as before a placeholder):

use ValidationLibrary.Phoenix.Controller,
  adapter: ValidationLibrary.Adapter.JSONSchema,
  resolver: {ValidationLibrary.Resolver.File, directory: "priv/schemas"}

use MyAppWeb, :controller

@validation_library schema: "show.json"
def show(conn, params) do
  # ...
end

Of course the whole adapter and resolver config can also be moved into config/:

config :validation_library,
  adapter: ValidationLibrary.Adapter.JSONSchema,
  resolver: {ValidationLibrary.Resolver.File, directory: "priv/schemas"}

Which would allow you to reduce the use to this:

use ValidationLibrary.Phoenix.Controller
use MyWebApp, :controller

# ...

There are a number of reasons I chose this API:

adapter and resolver being distinct

This allows the user to use the actual validation logic adapter with whatever kind of schema storage, be it local storage, remote storage (such as an S3 bucket) or even a full-blown schema registry.

A reasonable default for resolver would be local storage (ValidationLibrary.Resolver.File) which is probably perfectly fine for most use-cases.

The adapter can in turn focus on actually performing the validation, without having to care about where the schema came from. It gets the resolved schema, the data and then validates.

(In the earlier example I used JSONSchema as resolver because the local storage loading “just” loads the file without json parsing. I’ve now added an optional prepare/2 callback to the Adapter which transforms the schema from a plain string to an actual JSONSchema.)

@validation_library schema: "..."

The reason behind using a module attribute with the same name as the library is that you can overwrite any configuration here.

If you for example have this one endpoint which needs to accept XML to interact with some kind of legacy system, you could then do something like this:

@validation_library schema: "priv/schemas/legacy/create.xml", adapter: ValidationLibrary.Adapter.XML

But you’re certainly right that this isn’t really self-explanatory. It’s certainly feasibly to allow “aliases” of the “full” module attribute, such as the one you proposed (I would opt for namespacing though, to reduce the risk of name clashes, the final library name would be a lot shorter anyway).

@validation_library_request_schema "show.json"

Does that clarify things a bit, @dimitarvp? Any additional thoughts?

1 Like