Controller Schemas - TISTATechnologies/caseflow GitHub Wiki
Controller schemas are a way to perform validation on input data received by Rails controllers, as well as automatically generate documentation about the fields and their expected values. The generated documentation is served by the Rails app at /route_docs.
Adding a new schema
-
Add
include ValidationConcern
to the controller class, which uses a:before_action
hook to perform any desired validation, before a controller method is called. -
For a specific endpoint method, e.g.
def action
defined onExampleController
, validation is enabled by prepending a line likevalidates :action, using ExampleSchemas.action
. Methods without this line will skip schema validation. -
Continuing with the above example, create a new file for an
ExampleSchemas
class in theapp/schemas/
directory, with a class methodaction
that callsControllerSchema.params
orControllerSchema.json
and returns the resulting schema.- Note that the naming of this new class and class method, as well as the directory location, are determined by convention to mirror the controller class layout. Following convention is encouraged, although choosing different names merely requires updating the
validates
line.
- Note that the naming of this new class and class method, as well as the directory location, are determined by convention to mirror the controller class layout. Following convention is encouraged, although choosing different names merely requires updating the
-
Fill out the schema as desired, using the schema definition DSL.
ControllerSchema DSL
Although under the hood we use dry-schema which comes with a DSL, ControllerSchema
provides its own DSL as a thin layer of abstraction more in line with our documentation needs. An example is the easiest way to get a sense for this DSL:
def update_account
ControllerSchema.json do
integer :id
string :name
bool :paid_account
date :date_of_birth
datetime :last_login, nullable: true
string :team, optional: true, included_in?: %w[Instinct Mystic Valor], doc: "Pokemon Go team affiliation"
end
end
Each line in the schema defines a field in the input, and takes the form type :key, additional: arguments
Supported types
Supported types currently include bool, date, datetime, integer, and string, and are listed in ControllerSchema::SUPPORTED_TYPES
. Additional types can be added as long as they are supported by dry-schema, although dry-types makes it easy to implement new types.
Additional arguments
optional:
By default, fields are required, i.e. the key must be present in the input data. Optional fields don't have this restriction.nullable:
By default, fields must not have null values. Nullable fields don't have this restriction.included_in:
Specify a list of allowed values, for enumeration-style validation. Note that making a field nullable will implicitly include null as an allowed value.doc:
Provide additional context for this field.
Note that a field can be both required and nullable, or both optional and non-nullable (although this latter combination is probably rare).