Revisionair is a small Elixir library that allows you to create revisions, or versioning, of your data structures. Each time a data structure is updated, you can store the new version. Revisionair will keep track of the versions you have stored.
Revisionair is completely persistence-layer agnostic, meaning that regardless of if you use Ecto, Mnesia, Flat files, a simple ephemeral Agent,
or a complex sharded database setup with your toaster as extra redundancy,
you can use it with Revisionair, by simply implementing the Revisionair.Storage
behaviour.
Revisionair is available in Hex. The package can be installed
by adding revisionair
to your list of dependencies in mix.exs
:
def deps do
[{:revisionair, "~> 0.13.0"}]
end
- Whenever a data structure you care about changes, besides storing this latest revision at its primary location,
you also store it using Revisionair, using
Revisionair.store_revision(my_data_structure)
. - If you find out you liked an old version better, you can find it again by using
Revisionair.list_revisions(my_current_data_structure)
The lower-arity versions of Revisionair expect that you use structs that contain an :id
field: The :__struct__
key
is used to differentiate between different kinds of data (i.e. data types) that are stored, while the :id
field is used
to differentiate between different entities of this data type.
However, this is fully configurable. Revisionair's functions can be called with custom item_type
s and item_id
fields,
and when you pass (arity-1) functions as these arguments, they are called on the passed structure. So this also works:
%Car{uuid: "14dac99c-5dde-4301-846b-3d1fa21171cc", color: "black", number_of_wheels: 4}
|> Revisionair.store_revision(Vehicle, &(&1.uuid))
which might both be useful if you do not use an :id
field, or if you have structs whose
__struct__
type might change.
The persistence layer that Revisionair uses is fully configurable.
Which Revisionair.Storage implementation you use can be configured app-wide using the
config :revisionair, storage: Module.That.Implements.Revisionair.Storage
configuration setting.
When you want to override this setting, or have more complicated persistence needs (multiple different kinds of persistence in the same application?),
you can pass storage: Module.That.Implements.Revisionair.Storage
as option to all functions in the Revolutionair
module:
Revisionair.store_revision(my_structure, [storage: Revisionair.Storage.Agent])
# or:
Revisionair.store_revision(my_car, Vehicle, my_car.id, [storage: Revisionair.Storage.Agent])
# or:
Revisionair.store_revision(my_car, Vehicle, my_car.id, %{editor: current_user}, [storage: Revisionair.Storage.Agent])
Revisionair ships with a very simple Agent
layer that is used for testing.
For your practical applications, some other storage layer might be more appropriate. Check for instance revisionair_ecto for an Ecto-based persistence layer.
Other packages might be made by me or other people, that combine Revisionair with any of the databases and other persistence layers out there. They will be listed here.
Of course, writing your own Revisionair.Storage
implementation is very simple, as the behaviour only requires you to implement three functions.
If you want to store extra data, such as the time at which the revision took place, or who made the new revision,
you can do so by using the metadata
argument when using store_revision
.
This metadata is returned when list_revisions
or newest_revision
is called at a later time.
What information you store in here is completely up to you (but it is expected to be a map).
Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/revisionair.
- 0.13.4 Updates version of dev-dependency
ex_doc
which has not been updated for a long time. - 0.13.3 Fixing return value of
delete_all_revisions
. Thank you, @mindreframer! - 0.13 Renaming
structure_type
andunique_identifier
parameter names toitem_type
anditem_id
respectively, for brevity/readability. - 0.12 Possibility of passing extra options to the storage layer, under the
storage_options:
key. - 0.11 Rename
persistence:
option tostorage:
, as this follows the naming ofRevisionair.Storage
. - 0.10 Adds
Revisionair.get_revision
, and all revisions are now required to store a:revision
field, that allows you to track which exact revision some other part of your app is talking about. - 0.9.2 Some small bugfixes and improved documentation.
- 0.9 First publicly released version.