Versioning (Versioning v0.4.1) View Source

Versionings allow data to be changed to different versions of itself.

A the heart of our versioning is the Versioning struct. A Versioning struct contains the following fields:

  • :current - The current version that our data represents.
  • :target - The version that we want our data to be changed into.
  • :type - The type of data we are working with. If we are working with structs, this will typically be the struct name in string format, eg: "Post"
  • :data - The underlying data that we want to change. For structs, like our Post, be aware that we typically have our data as a bare map since it is easier to transform.
  • :changes - A list of change modules that have been applied against the versioning. The first change module would be the most recent module run.
  • :changed - A boolean representing if change modules have been applied.
  • :assigns - A map of arbitrary data we can use to store additonal information in.

Example

Versioning.new(%Post{}, "2.0.0", "1.0.0")

With the above, we have created a versioning of a Post struct. This represents us wanting to transform our post from a version "2.0.0" to an older "1.0.0" version.

Schemas

The versioning struct is used in combination with a Versioning.Schema, which allows us to map out the changes that should occur through versions. Please see the Versioning.Schema documentation for more details.

Link to this section Summary

Functions

Assigns a value to a key in the versioning.

Fetches the value for a specific key in the data of versioning.

Gets the value for a specific key in the data of versioning.

Creates a new versioning using the data provided.

Returns and removes the value associated with key within the data of versioning.

Puts the current version that the data represents.

Puts the full data in the versioning.

Puts the given value under key within the data of versioning.

Puts the target version that the data will be transformed to.

Puts the type of the versioning data.

Updates the key within the data of versioning using the given function.

Link to this section Types

Specs

assigns() :: %{optional(atom()) => any()}

Specs

data() :: %{optional(binary()) => any()}

Specs

t() :: %Versioning{
  assigns: assigns(),
  changed: boolean(),
  changes: [Versioning.Change.t()],
  current: version(),
  data: map(),
  parsed_current: term(),
  parsed_target: term(),
  schema: Versioning.Schema.t(),
  target: version(),
  type: type()
}

Specs

type() :: binary() | nil

Specs

version() :: binary() | nil

Link to this section Functions

Link to this function

assign(versioning, key, value)

View Source

Specs

assign(t(), atom(), any()) :: t()

Assigns a value to a key in the versioning.

The “assigns” storage is meant to be used to store values in the versioning so that change modules in your schema can access them. The assigns storage is a map.

Examples

iex> versioning.assigns[:hello]
nil
iex> versioning = Versioning.assign(versioning, :hello, :world)
iex> versioning.assigns[:hello]
:world
Link to this function

fetch_data(versioning, key)

View Source

Specs

fetch_data(t(), binary()) :: {:ok, any()} | :error

Fetches the value for a specific key in the data of versioning.

If data contains the given key with value value, then {:ok, value} is returned. If data doesn't contain key, :error is returned.

Examples

iex> Versioning.fetch_data(versioning, "foo")
{:ok, "bar"}
iex> Versioning.fetch_data(versioning, "bar")
:error
Link to this function

get_data(versioning, key, default \\ nil)

View Source

Specs

get_data(t(), binary(), term()) :: any()

Gets the value for a specific key in the data of versioning.

If key is present in data with value value, then value is returned. Otherwise, default is returned (which is nil unless specified otherwise).

Examples

iex> Versioning.get_data(versioning, "foo")
"bar"
iex> Versioning.get_data(versioning, "bar")
nil
iex> Versioning.get_data(versioning, "bar", "baz")
"baz"
Link to this function

new(data \\ %{}, current \\ nil, target \\ nil, type \\ nil)

View Source

Specs

new(map(), version(), version(), type()) :: Verisoning.t()

Creates a new versioning using the data provided.

If a struct is the data, and no type is provided, the struct module is set as the versioning :type (as described in put_type/2), and the struct is turned into a string-key map that is used for the :data.

Examples

# These are equivalent
Versioning.new(%{"foo" => "bar"}, "2.0.0", "1.0.0", SomeData)
Versioning.new(%{foo: "bar"}, "2.0.0", "1.0.0", "SomeData")
Versioning.new(%SomeData{foo: "bar"}, "2.0.0", "1.0.0")
Link to this function

pop_data(versioning, key, default \\ nil)

View Source

Returns and removes the value associated with key within the data of versioning.

If key is present in data with value value, {value, new_versioning} is returned where new_versioning is the result of removing key from data. If key is not present in data, {default, new_versioning} is returned.

Examples

iex> Versioning.pop_data(versioning, "foo")
{"bar", versioning}
iex> Versioning.pop_data(versioning, "foo")
{nil, versioning}
Link to this function

put_current(versioning, current)

View Source

Specs

put_current(t(), version()) :: t()

Puts the current version that the data represents.

The version should be represented somewhere within your Versioning.Schema. This will become the "starting" point from which change modules will be run.

Examples

Versioning.put_current(versioning, "0.1.0")
Link to this function

put_data(versioning, data)

View Source

Specs

put_data(t(), map()) :: t()

Puts the full data in the versioning.

The data represents the base of what will be modified when a versioning is run through a schema.

Data must be a map. If a struct is provided, the struct will be turned into a basic map - though its type information will not be inferred.

The keys of data will always be strings. If passed an

Examples

iex> versioning = Versioning.put_data(versioning, %{"foo" => "bar"})
iex> versioning.data
%{"foo" => "bar"}
Link to this function

put_data(versioning, key, value)

View Source

Specs

put_data(t(), binary(), any()) :: t()

Puts the given value under key within the data of versioning.

Examples

iex> Versioning.put_data(versioning, "foo", "bar")
iex> versioning.data["foo"]
"bar"
Link to this function

put_target(versioning, target)

View Source

Specs

put_target(t(), version()) :: t()

Puts the target version that the data will be transformed to.

The version should be represented somewhere within your Versioning.Schema. Once the change modules in the target version are run, no more changes will be made.

Examples

Versioning.put_target(versioning, "0.1.0")
Link to this function

put_type(versioning, type)

View Source

Specs

put_type(t(), type() | atom()) :: t()

Puts the type of the versioning data.

Typically, if working with data that is associated with a struct, this will be the struct trailing module name in binary format. For example, MyApp.Foo will be represented as "Foo".

When running a versioning through a schema, only the changes that match the type set on the versioning will be run.

Examples

# These are equivalent
Versioning.put_type(versioning, "Post")
Versioning.put_type(versioning, MyApp.Post)
Link to this function

update_data(versioning, key, fun)

View Source

Specs

update_data(t(), binary(), (any() -> any())) :: t()

Updates the key within the data of versioning using the given function.

If the data does not contain key - nothing occurs. If it does, the fun is invoked with argument value and its result is used as the new value of key.

Examples

iex> Versioning.update_data(versioning, "foo", fn _val -> "bar" end)
iex> versioning.data["foo"]
"bar"