lib/gsmlg/mnesia/query/data.ex

defmodule GSMLG.Mnesia.Query.Data do
  @moduledoc """
  Helper module that acts as an interface to convert GSMLG.Mnesia Table
  data structs into Mnesia data tuples and vice versa.

  This is responsible for automatically handling conversions
  between data in methods defined in the Query module, so you
  won't need to use this at all.


  ## Usage

  Given a GSMLG.Mnesia Table:

  ```
  defmodule MyApp.User do
    use GSMLG.Mnesia.Table, attributes: [:id, :name]
  end
  ```

  You can convert its structs to Mnesia format:

  ```
  GSMLG.Mnesia.Query.Data.dump(%MyApp.User{id: 1, name: "Sye"})
  # => {MyApp.User, 1, "Sye"}
  ```

  Or convert it back to a struct:

  ```
  GSMLG.Mnesia.Query.Data.load({MyApp.User, 2, "Rick"})
  # => %MyApp.User{id: 2, name: "Rick"}
  ```
  """

  # Public API
  # ----------

  @doc """
  Convert Mnesia data tuple into GSMLG.Mnesia Table struct.

  Use this method when reading data from an Mnesia database. The
  data should be in a tuple format, where the first element is
  the Table name (`GSMLG.Mnesia.Table` definition).

  This will automatically match the the tuple values against the
  table's attributes and convert it into a struct of the GSMLG.Mnesia
  table you defined.
  """
  @spec load(tuple) :: GSMLG.Mnesia.Table.record()
  def load(data) when is_tuple(data) do
    [table | values] = Tuple.to_list(data)

    values =
      table.__info__()
      |> Map.get(:attributes)
      |> Enum.zip(values)

    struct(table, values)
  end

  @doc """
  Convert GSMLG.Mnesia Table struct into Mnesia data tuple.

  Use this method when writing data to an Mnesia database. The
  argument should be a struct of a previously defined GSMLG.Mnesia
  table definition, and this will convert it into a tuple
  representing an Mnesia record.
  """
  @spec dump(GSMLG.Mnesia.Table.record()) :: tuple
  def dump(data = %{__struct__: table}) do
    values =
      table.__info__()
      |> Map.get(:attributes)
      |> Enum.map(&Map.get(data, &1))

    List.to_tuple([table | values])
  end
end