Rolodex v0.4.0 Rolodex.Schema
Exposes functions and macros for working with request and response parameters.
It includes two macros. Used together, they will setup reuseable schemas for things like API responses.
It also exposes the following functions:
is_schema_module?/1
- determines if the provided item is a module that has defined a reuseable schemato_map/1
- serializes a schema module into a map for use by aRolodex.Processor
behaviournew_field/1
- parses a schema field into a map of metadata. Thefield/3
macro uses this function to parse the metadata passed in. This function is also called when parsing all controller action@doc
parameter annotationsget_refs/1
- takes a schema or map and traverses it, looking for any nested references to schemas within
Link to this section Summary
Functions
Adds a new field to the schema. Will generate a method __field__/1
where the
one argument is the field identifier
. This can be used to fetch the field
metadata later
Returns a unique list of all nested Rolodex.Schema
refs within the current field
map or schema module
Determines if an arbitrary item is a module that has defined a reusable schema
via Rolodex.Schema
macros
Parses data for schema fields and controller action parameter annotations.
Resolves references to any nested Rolodex.Schema
modules within. Generates
a new map representing the field in a standardized format
Opens up the schema definition for the current module. Will name the schema
and generate metadata for the schema based on subsequent calls to field/3
Serializes the Rolodex.Schema
metadata defined for the given module into an
object, using the new_field/1
helper
Link to this section Functions
field(identifier, type, opts \\ []) (macro)
Adds a new field to the schema. Will generate a method __field__/1
where the
one argument is the field identifier
. This can be used to fetch the field
metadata later.
Accepts
identifier
- field nametype
- either an atom or another Rolodex.Schema moduleopts
- a keyword list of options, looks fordesc
andof
(for array types)
Example
defmodule MySchema do
use Rolodex.Schema
schema "MySchema", desc: "Example schema" do
# Atomic field with no description
field :id, :uuid
# Atomic field with a description
field :name, :string, desc: "The object's name"
# A field that refers to another, nested object
field :other, OtherSchema
# A field that is an array of items of one-or-more types
field :multi, :list, of: [:string, OtherSchema]
# A field that is one of the possible provided types
field :any, :one_of, of: [:string, OtherSchema]
end
end
get_refs(field)
Returns a unique list of all nested Rolodex.Schema
refs within the current field
map or schema module.
Examples
iex> defmodule NestedSchema do
...> use Rolodex.Schema
...>
...> schema "NestedSchema" do
...> field :id, :uuid
...> end
...> end
iex>
iex> defmodule TopSchema do
...> use Rolodex.Schema
...>
...> schema "TopSchema", desc: "An example" do
...> # Atomic field with no description
...> field :id, :uuid
...>
...> # Atomic field with a description
...> field :name, :string, desc: "The schema's name"
...>
...> # A field that refers to another, nested object
...> field :other, NestedSchema
...>
...> # A field that is an array of items of one-or-more types
...> field :multi, :list, of: [:string, NestedSchema]
...>
...> # A field that is one of the possible provided types
...> field :any, :one_of, of: [:string, NestedSchema]
...> end
...> end
iex>
iex> # Searching for refs in a formatted map
iex> Rolodex.Schema.new_field(type: :list, of: [TopSchema, NestedSchema])
...> |> Rolodex.Schema.get_refs()
[Rolodex.SchemaTest.NestedSchema, Rolodex.SchemaTest.TopSchema]
iex>
iex> # Searching for refs in an arbitrary map
iex> Rolodex.Schema.get_refs(%{id: :uuid, nested: TopSchema})
[Rolodex.SchemaTest.NestedSchema]
iex>
iex> # Search for refs in a schema
iex> Rolodex.Schema.get_refs(TopSchema)
[Rolodex.SchemaTest.NestedSchema]
is_schema_module?(item)
Determines if an arbitrary item is a module that has defined a reusable schema
via Rolodex.Schema
macros
Example
iex> defmodule SimpleSchema do
...> use Rolodex.Schema
...> schema "SimpleSchema", desc: "Demo schema" do
...> field :id, :uuid
...> end
...> end
iex>
iex> # Validating a schema module
iex> Rolodex.Schema.is_schema_module?(SimpleSchema)
true
iex> # Validating some other module
iex> Rolodex.Schema.is_schema_module?(OtherModule)
false
Parses data for schema fields and controller action parameter annotations.
Resolves references to any nested Rolodex.Schema
modules within. Generates
a new map representing the field in a standardized format.
Every field within the map returned will have a type
. Some fields, like lists
and objects, have other data nested within. Other fields hold references (called
refs
) to Rolodex.Schema
modules.
You can think of the output as an AST of parameter data that a Rolodex.Processor
behaviour can accept for writing out to a destination.
Examples
Parsing primitive data types (e.g. string
)
# Creating a simple field with a primitive type
iex> Rolodex.Schema.new_field(:string)
%{type: :string}
# With additional options
iex> Rolodex.Schema.new_field(type: :string, desc: "My string")
%{type: :string, desc: "My string"}
Parsing collections: objects and lists
# Create an object
iex> Rolodex.Schema.new_field(type: :object, properties: %{id: :uuid, name: :string})
%{
type: :object,
properties: %{
id: %{type: :uuid},
name: %{type: :string}
}
}
# Shorthand for creating an object: a top-level map or keyword list
iex> Rolodex.Schema.new_field(%{id: :uuid, name: :string})
%{
type: :object,
properties: %{
id: %{type: :uuid},
name: %{type: :string}
}
}
# Create a list
iex> Rolodex.Schema.new_field(type: :list, of: [:string, :uuid])
%{
type: :list,
of: [
%{type: :string},
%{type: :uuid}
]
}
# Shorthand for creating a list: a list of types
iex> Rolodex.Schema.new_field([:string, :uuid])
%{
type: :list,
of: [
%{type: :string},
%{type: :uuid}
]
}
Arbitrary collections
Use the one_of
type to describe a field that can be one of the provided types
iex> Rolodex.Schema.new_field(type: :one_of, of: [:string, :uuid])
%{
type: :one_of,
of: [
%{type: :string},
%{type: :uuid}
]
}
Working with schemas
iex> defmodule DemoSchema do
...> use Rolodex.Schema
...>
...> schema "DemoSchema" do
...> field :id, :uuid
...> end
...> end
iex>
iex> # Creating a field with a [`Rolodex.Schema`](#content) as the top-level type
iex> Rolodex.Schema.new_field(DemoSchema)
%{type: :ref, ref: Rolodex.SchemaTest.DemoSchema}
iex>
iex> # Creating a collection field with various members, including a nested schema
iex> Rolodex.Schema.new_field(type: :list, of: [:string, DemoSchema])
%{
type: :list,
of: [
%{type: :string},
%{type: :ref, ref: Rolodex.SchemaTest.DemoSchema}
]
}
schema(name, opts \\ [], list) (macro)
Opens up the schema definition for the current module. Will name the schema
and generate metadata for the schema based on subsequent calls to field/3
Accepts
name
- the schema nameopts
- a keyword list of options (currently, only looks for adesc
key)block
- the inner schema definition with one or more calls tofield/3
Example
defmodule MySchema do
use Rolodex.Schema
schema "MySchema", desc: "Example schema" do
# Atomic field with no description
field :id, :uuid
# Atomic field with a description
field :name, :string, desc: "The object's name"
# A field that refers to another, nested object
field :other, OtherSchema
# A field that is an array of items of one-or-more types
field :multi, :list, of: [:string, OtherSchema]
# A field that is one of the possible provided types
field :any, :one_of, of: [:string, OtherSchema]
end
end
to_map(schema)
Serializes the Rolodex.Schema
metadata defined for the given module into an
object, using the new_field/1
helper.
Example
iex> defmodule OtherSchema do
...> use Rolodex.Schema
...>
...> schema "OtherSchema" do
...> field :id, :uuid
...> end
...> end
iex>
iex> defmodule MySchema do
...> use Rolodex.Schema
...>
...> schema "MySchema", desc: "An example" do
...> # Atomic field with no description
...> field :id, :uuid
...>
...> # Atomic field with a description
...> field :name, :string, desc: "The schema's name"
...>
...> # A field that refers to another, nested object
...> field :other, OtherSchema
...>
...> # A field that is an array of items of one-or-more types
...> field :multi, :list, of: [:string, OtherSchema]
...>
...> # A field that is one of the possible provided types
...> field :any, :one_of, of: [:string, OtherSchema]
...> end
...> end
iex>
iex> Rolodex.Schema.to_map(MySchema)
%{
type: :object,
desc: "An example",
properties: %{
id: %{type: :uuid},
name: %{desc: "The schema's name", type: :string},
other: %{type: :ref, ref: Rolodex.SchemaTest.OtherSchema},
multi: %{
type: :list,
of: [
%{type: :string},
%{type: :ref, ref: Rolodex.SchemaTest.OtherSchema}
]
},
any: %{
type: :one_of,
of: [
%{type: :string},
%{type: :ref, ref: Rolodex.SchemaTest.OtherSchema}
]
}
}
}