MishkaBlog.Resources.Changes.RestoreVersion (Mishka Blog v0.0.1)

Copy Markdown View Source

Restores a record to one of its own versions, named by the action's :version_id argument.

A version of any other record, of this site or another, is refused with refusal/1, and a version that does not exist with a not-found error. Only the attributes in :fields are copied back, and never site_id, so a restore cannot move a record to another site. The check holds for a call made with authorize?: false too.

Usage

update :restore_version do
  accept []
  argument :version_id, :uuid, allow_nil?: false

  change {MishkaBlog.Resources.Changes.RestoreVersion,
          version: MishkaBlog.Tag.Version,
          fields: [:name, :slug, :description],
          label: "tag"}
end

Options

  • :version - Required. The record's version resource. It needs a :get_any read.
  • :fields - Required. The attributes a restore copies back.
  • :label - Required. How the refusal names the record, such as "tag".

Summary

Functions

changes with the string value of field read through the attribute's own type on resource: "active" becomes :active for an atom attribute. A value the type refuses is dropped, so the record keeps its current one; a field that is absent or not a string is left as it is.

The entries of a version's changes whose key names one of fields, keyed by that atom. A key that names no field is left out, so reading a version never creates an atom

Each of records as it was in the version version_id, read with read_opts (the caller's actor, tenant and authorize?) through the version's :get_any read

The refusal of a version that is another record's: "Version does not belong to this {label}.", translated in the errors domain of MishkaCmsCore.Gettext in the locale of the calling process, label translated there too. A preview of another record's version is refused with it as well.

Functions

cast_field(changes, resource, field)

@spec cast_field(%{required(atom()) => term()}, Ash.Resource.t(), atom()) :: %{
  required(atom()) => term()
}

changes with the string value of field read through the attribute's own type on resource: "active" becomes :active for an atom attribute. A value the type refuses is dropped, so the record keeps its current one; a field that is absent or not a string is left as it is.

known_changes(changes, fields)

@spec known_changes(map() | String.t() | nil, [atom()]) :: %{
  required(atom()) => term()
}

The entries of a version's changes whose key names one of fields, keyed by that atom. A key that names no field is left out, so reading a version never creates an atom:

known_changes(%{"name" => "Elixir", "junk" => 1}, [:name, :slug]) #=> %{name: "Elixir"}

changes may be a map with string or atom keys, or its JSON; anything else, JSON that does not parse or is not an object included, reads as %{}.

preview(records, opts, version_id, read_opts)

@spec preview([struct()], keyword(), String.t(), keyword()) ::
  {:ok, [struct()]} | {:error, Exception.t()}

Each of records as it was in the version version_id, read with read_opts (the caller's actor, tenant and authorize?) through the version's :get_any read:

preview(results, [version: MishkaBlog.Tag.Version, label: "tag"], version_id,
        Ash.Scope.to_opts(context))

opts are the options of this change, :version and :label, and two more:

  • :fields - The attributes copied from the version. Defaults to every field of the record.
  • :cast - Fields whose string value is read through the attribute's own type, as cast_field/3 does. Defaults to none.

A version that belongs to another record is refused with refusal/1 of :label, and one that cannot be read comes back as the read's own error. Neither raises.

refusal(label)

@spec refusal(String.t()) :: String.t()

The refusal of a version that is another record's: "Version does not belong to this {label}.", translated in the errors domain of MishkaCmsCore.Gettext in the locale of the calling process, label translated there too. A preview of another record's version is refused with it as well.