README.md

[![build status](https://gitlab.com/mucky-pup/mecto/badges/main/pipeline.svg)](https://gitlab.com/mucky-pup/mecto/-/commits/main)
[![coverage report](https://gitlab.com/mucky-pup/mecto/badges/main/coverage.svg)](https://mucky-pup.gitlab.io/mecto/coverage/excoveralls.html)
[![documentation coverage](https://ik.imagekit.io/muckypup/mecto/doc-coverage.svg)](https://hexdocs.pm/mecto)
[![License: CC BY-SA 4.0](https://img.shields.io/badge/License-CC%20BY--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-sa/4.0/)

# Mecto

"Mail merging" with Ecto structs.

A parser to interpolate MediaWiki-like `[[foo.bar]]` markup using data from Ecto schemas.

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `mecto` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:mecto, "~> 0.7.0"}
  ]
end
```

## Usage

Mecto was originally built to provide dynamic "mail-merging" (think HEEx, but not compiled) from Elixir structs - specifically ones that `use Ecto.Schema`.

Take this struct:

```elixir
defmodule MyApp.BlogPost do
  use Ecto.Schema

  schema "blog_posts" do
    field(:title, :string)
    field(:content, :string)
  end
end
```

You could then have some text like:

```elixir
text = "The latest blog post is [[blog_post.title]]"
```

If you wanted to validate the text has correct markup, you could call:

```elixir
Mecto.validate(text, MyApp.BlogPost)

> %{blog_post: %{title: :string}}
```

And Mecto would ensure that the fields used in the text actually exist on `MyApp.BlogPost`. You can also take it a step further,
calling `Mecto.interpolate` to then use the values in a specific struct:

```elixir
Mecto.interpolate(text, %MyApp.BlogPost{title: "some title"})

> {:ok, "The latest blog post is some title"}
```

Mecto also handles relationships and custom Ecto types (i.e. defined with `Ecto.Type`).

By default there is [an implementation](https://gitlab.com/mucky-pup/mecto/-/blob/main/lib/custom_schema.ex) for `Ecto.Enum`,
but you can use [protocol_ex](https://github.com/OvermindDL1/protocol_ex) for your own types - this is required for them as
Elixir doesn't allow protocol dispatch on atoms (module names), only data...which Mecto doesn't have when parsing markup.

See the tests for more examples.

Documentation can be found at <https://hexdocs.pm/mecto>.

## Support my work

If you want to support my work, you can donate on Liberapay:

[![Liberapay donation link](https://liberapay.com/assets/widgets/donate.svg)](https://liberapay.com/mucky-pup-creations/donate)