# `MishkaCmsBuilder.Plugins.ReleaseDraftHistory`
[🔗](https://github.com/mishka-group/mishka_cms_builder/blob/v0.0.1-alpha.2/lib/mishka_cms_builder/plugins/release_draft_history.ex#L5)

Detaches a deleted draft's editing history from it, so the rows survive and join the live
record's own timeline.

One plugin per destroy action of the three draft resources, each on the announcement
`MishkaCmsCore.Runtime.Resources.Notifiers.PluginHook` fires after the destroy commits:
`cms_core:page_draft:after_destroy` and `cms_core:page_draft:after_master_destroy`, and the same
two for `layout_draft` and `error_page_draft`. A master's delete runs the `master_destroy` twin,
which fires its own event, so both are listened on.

## Why this is not a foreign key

It was one. `MishkaCmsBuilder.HistoryEvent.draft_id` was a `belongs_to` to
`MishkaCmsCore.Runtime.PageDraft` with `on_delete: :nilify`, which did exactly this job — for
pages. But `source_type` names all four editable kinds and three of them keep their drafts in
tables of their own, so a change made on a layout's or an error page's draft violated that one key
and the row was refused: the History sheet was simply empty for those two sections.

A single key cannot name three tables, so the column became a plain id and the nilify moved to
the draft resources' own destroy — the same level the constraint was at, rather than any one
caller. That matters because a draft is deleted from several places: the picker's Delete goes
through the resource's own destroy, publishing spends the draft through
`MishkaCmsCore.Runtime.Authoring.Drafts.discard/3`, and the twenty-draft sweep prunes through
`prune/3`. Only the resource sees all of them, and its announcements are how the editor hears of
each without the drafts naming the editor.

## Best effort, deliberately

The release runs after the delete has committed and never undoes it: a draft the author asked to
delete must go even if its history could not be released. A row left pointing at a draft that no
longer exists is invisible rather than wrong — no read names a dead branch — so a failure is
logged and the record is handed back as it came. It is never raised: a plugin that raises is
skipped by the event, and the reason would be lost.

# `__using__`
*macro* 

Turns the module into the plugin on `event`, releasing the history of the draft it announces.

    use MishkaCmsBuilder.Plugins.ReleaseDraftHistory,
      event: PluginHook.event_name(MishkaCmsCore.Runtime.PageDraft, :destroy)

# `release`

```elixir
@spec release(String.t(), map() | nil) :: :ok
```

Sets `draft_id` to `nil` on every history row recorded on `draft_id`, as `actor`. Always `:ok`;
a failure is logged.

---

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