# `Ymlr.Encoder`
[🔗](https://github.com/ufirstgroup/ymlr/blob/v5.1.5/lib/ymlr/encoder.ex#L1)

Protocol controlling how a value is encoded to YAML.

## Deriving

The protocol allows leveraging the Elixir's `@derive` feature to simplify
protocol implementation in trivial cases. Accepted options are:

  * `:only` - encodes only values of specified keys.
  * `:except` - If set to a list of fields, all struct fields except specified
    keys are encoded. If set to `:defaults`, all fields are encoded, except
    the ones equaling their default value as defined in the struct.

By default all keys except the `:__struct__` key are encoded.

## Example

Let's assume a presence of the following struct:

```
defmodule Test do
  defstruct [:foo, :bar, :baz]
end
```

If we were to call `@derive Ymlr.Encoder` just before `defstruct`, an
implementation similar to the following implementation would be generated:

```
defimpl Ymlr.Encoder, for: Test do
  def encode(data, indent_level) do
    data
    |> Map.take(unquote([:foo, :bar, :baz]))
    |> Ymlr.Encode.map(indent_level)
  end
end
```

### Limit fields using the `only` Option

We can limit the fields being encoded using the `:only` option:

```
defmodule Test do
  @derive {Ymlr.Encoder, only: [:foo]}
  defstruct [:foo, :bar, :baz]
end
```

This would generate an implementation similar to the following:

```
defimpl Ymlr.Encoder, for: Test do
  def encode(data, indent_level) do
    data
    |> Map.take(unquote([:foo]))
    |> Ymlr.Encode.map(indent_level)
  end
end
```

### Exclude fields using the `except` Option

We can exclude the fields being encoded using the `:except` option:

```
defmodule Test do
  @derive {Ymlr.Encoder, except: [:foo]}
  defstruct [:foo, :bar, :baz]
end
```

This would generate an implementation similar to the following:

```
defimpl Ymlr.Encoder, for: Test do
  def encode(data, indent_level) do
    data
    |> Map.take(unquote([:bar, :baz]))
    |> Ymlr.Encode.map(indent_level)
  end
end
```

We can exclude the fields being left at their defaults by passing `except:
:defaults`:

```
defmodule TestExceptDefaults do
  @derive {Ymlr.Encoder, except: :defaults}
  defstruct [:foo, bar: 1, baz: :ok]
end
```

This would generate an implementation similar to the following:

```
iex> Ymlr.document!(%TestExceptDefaults{foo: 1, bar: 1, baz: :error})
"baz: error\nfoo: 1"
```

# `opts`

```elixir
@type opts() :: keyword()
```

# `t`

```elixir
@type t() :: term()
```

All the types that implement this protocol.

# `encode`

```elixir
@spec encode(data :: term(), indent_level :: integer(), opts :: opts()) :: iodata()
```

Encodes the given data to YAML.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
