module Versionomy::Schema

Version number schema.

A schema defines the structure and semantics of a version number. The schema controls what fields are present in the version, how version numbers are compared, what the default values are, and how values can change. Version numbers with the same schema can be compared with one another, and version numbers can be converted trivially to formats that share the same schema, without requiring a Conversion implementation.

At its simplest, a version number is defined as a sequence of fields, each with a name and data type. These fields may be integer-valued, string-valued, or symbolic, though most will probably be integers. Symbolic fields are enumerated types that are useful, for example, if you want a field to specify the type of prerelease (e.g. “alpha”, “beta”, or “release candidate”).

As a simple conceptual example, you could construct a schema for version numbers of the form “major.minor.tiny” like this. (This is a conceptual diagram, not actual syntax.)

("major": integer), ("minor": integer), ("tiny": integer)

More generally, fields are actually organized into a DAG (directed acyclic graph) in which the “most significant” field is the root, the next most significant is a child of that root, and so forth down the line. The simple schema above, then, is actually represented as a linked list (a graph with one path), like this:

("major": integer) ->
    ("minor": integer) ->
        ("tiny": integer) ->
            nil

It is, however, possible for the form of a field to depend on the value of the previous field. For example, suppose we wanted a schema in which if the value of the “minor” field is 0, then the “tiny” field doesn't exist. e.g.

("major": integer) ->
    ("minor": integer) ->
        [value == 0] : nil
        [otherwise]  : ("tiny": integer) ->
            nil

The Versionomy::Schema::Field class represents a field in this graph. The Versionomy::Schema::Wrapper class represents a full schema object.

Generally, you should create schemas using Versionomy::Schema#create. That method provides a DSL that lets you quickly create the fields.

Public Class Methods

create(field_=nil, opts_={}, &block_) click to toggle source

Creates a schema. Returns an object of type Versionomy::Schema::Wrapper.

You may either pass a root field, or provide a block to use to build fields. If you provide a block, you must use the methods in Versionomy::Schema::Builder in the block to create the root field.

# File lib/versionomy/schema/wrapper.rb, line 49
def self.create(field_=nil, opts_={}, &block_)
  if field_ && block_
    raise ::ArgumentError, 'You may provide either a root field or block but not both'
  end
  if block_
    builder_ = Schema::Builder.new
    ::Blockenspiel.invoke(block_, builder_)
    field_ = builder_._get_field
    modules_ = builder_._get_modules
    aliases_ = builder_._get_aliases
  else
    modules_ = opts_[:modules] || []
  end
  Schema::Wrapper.new(field_, modules_, aliases_)
end