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?