Cartograf v0.2.0 Cartograf View Source

Cartograf is a set of elixir macros for mapping fields from one struct to another. The goal is to make these struct-to-struct translations more robust and less cumbersome to write and maintian.

Basic Form

The basic form for using this module is of the form:

map Proj.A, Proj.B, :one_to_one do
    let :a, :aa
    let :b, :bb
    let :c, :cc
    let :d, :dd
end

This structure would create a function called one_to_one/1 within whatever module this the macro was invoked within. The one_to_one/1 function would expect a struct of type Proj.A and return a struct of type Proj.B would be returned.

This Map generates a function that contains a native elixir struct syntax for the destination struct. For instance, for the Basic Example, the following function is generated.

def one_to_one(bnd = %Proj.A{}) do
  %Proj.B{aa: bnd.a, bb: bnd.b, cc: bnd.c, dd: bnd.d}
end

Key Notes

cartograf is supposed to be a tool, not a hazard. The point of this project is to create robust mappings from one struct to another. As such, there are a few safeties in place to protect the developer.

  • map() does require that its input struct is of the correct type. The function generated leverages pattern matching on the argument to ensure that the struct type is the one declared when the map was specified.
  • All input fields should be handled. Each map() will report any unmapped fields as a warning at compile time. This can also be configured to not report a warning, fail compilation, for more info see Config. In order to remove these warnings, a drop(input_key) should be added to the map() The main purpose for this is catch instances where developers add fields to structs, but fail to update the maps.
  • Maps do not automatically map identical keys from one struct to another by default. To enable this, the auto: true option must be set in the map’s options.

Configuration

Cartograf by default will warn about any unmapped fields to change this behaviour the following configuration changes can be made.

  • config :cartograf, on_missing_key: :warn

    Log warning for each unmapped field

  • config :cartograf, on_missing_key: :ignore

    Ignore unmapped fields, don’t warn or throw

  • config :cartograf, on_missing_key: :throw

    Raise an exception on unmapped fields, halting compilation

Link to this section Summary

Functions

Allow for a field in the output to be set to a constant value

Allow for a field from the input to be excluded from the output

Specify where the a field in the input should be mapped to in the out

Creates a function in the the current module for mapping from struct to another

Used to specify a nested map within map()

Link to this section Functions

Link to this macro const(dest_key, val) View Source (macro)
const(atom(), any()) :: any()

Allow for a field in the output to be set to a constant value.

Link to this macro drop(src_key) View Source (macro)
drop(atom()) :: any()

Allow for a field from the input to be excluded from the output.

Most useful when using auto, however it is recommended to use this for any non-mapped.

Link to this macro let(source_key, dest_key) View Source (macro)
let(atom(), atom()) :: any()

Specify where the a field in the input should be mapped to in the out.

Link to this macro map(from_t, to_t, name, opts \\ [], list) View Source (macro)
map(module(), module(), atom(), [], [{:do, any()}]) :: any()

Creates a function in the the current module for mapping from struct to another.

defmodule A, do: defstruct [:a, :b, :c]
defmodule B, do: defstruct [:aa, :bb, :cc]
defmodule YourModule do
  use Cartograf
  map A, B, :a_to_b do
      let :a, :aa
      let :b, :bb
      let :c, :cc
  end
end
  iex> YourModule.a_to_b(%A{a: 1, b: "2", c: :d})
  %B{aa: 1, bb: "2", cc: :d}

The options:

  • auto: true create bindings for all matching keys of the two structs which are not already mapped
  • map: true create a second anologous method 'name'_map which will return a map instead of the struct (some libraries rely of creating a struct for you from a map of fields)
Link to this macro nest(dest_key, to_t, list) View Source (macro)
nest(atom(), module(), [{:do, any()}]) :: any()

Used to specify a nested map within map().

This resulting struct will have the type of to_t. No options are available for this macro.