# `MishkaSlug.Change`
[🔗](https://github.com/mishka-group/mishka_slug/blob/v0.0.1/lib/mishka_slug/change.ex#L50)

An Ash change that writes a slug made by `MishkaSlug.slugify/2`.

    changes do
      change {MishkaSlug.Change, from: :title, into: :slug, language: :language,
              locales: {MyApp.Sites, :languages, []}, keep: [".", "_"]}
    end

The change reads `:from` from the action's arguments or changes and does nothing when it is
not there. A value that is not a string, or a title that gives no slug, is a changeset error on
`:from`; the slug attribute is never set to `nil` or `""`. The error texts go through Gettext
(see `MishkaSlug.Messages`) in the locale of the calling process. When `:max_length` is not given, the
`max_length` constraint of the `:into` attribute is used.

## Options

The options of `MishkaSlug.slugify/2` (see `MishkaSlug.Options`) are accepted as they are,
except `:language` and `:locales`, which take more here. Unknown options and invalid values
make `init/1` return an error. These are the change's own:

  * `:from` - `atom()`, required. The attribute or argument the slug is made from, such as
    `:title`.

  * `:into` - `atom() | nil`, default `nil`. The attribute the slug is written to. Defaults
    to `:from`.

  * `:skip_if_present?` - `boolean()`, default `false`. Leave the slug alone when the action
    already sets `:into`.

  * `:language` - `atom() | String.t() | nil`, default `nil`. The text's language: an
    attribute or argument name read from the changeset (such as `:language`), or a fixed
    code.

  * `:locales` - `[String.t()] | {module, function, args}`, default `[]`. The site's
    languages: a list, or `{module, function, args}` called with the changeset first, so a
    CMS can read them for the changeset's tenant.

# `slug_options`

```elixir
@spec slug_options(keyword(), Ash.Changeset.t()) :: keyword()
```

Returns the `MishkaSlug.slugify/2` options this change uses for a changeset.

It resolves `:language` and `:locales` against the changeset and fills `:max_length` from the
`:into` attribute, so code that makes a slug outside an action (a preview in a form, for
example) gets the same slug the action will write.

---

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