View Source Eakins.Schema (eakins v0.0.1)

A schema extension that allows you to attach images to a model.

To use this extension, your schema must define an integer field called :version and a map field. The map field's name should be the same as the image map or image list that you will define.

To configure this module, just use it below your usage of Eakins.Schema. Then, define eith an image_map or image_list in your schema.

defmodule Myapp.User do
  use Ecto.Schema
  use Eakins.Schema
  schema "users" do
    field :first_name, :string
    field :last_name, :string
    image_map :avatars
  end
end

The previous incantation will define an image map and associate with the images field. The name of the image list or the image map should be plural, as the functions that are generated make use of this name to provide access to the entire list (the plural functions) or a single image (the singular functions).

Image Maps

An image map is an unordered collection of named images. Eakins in this collection can be added, removed or accessed by their name. Similarly, you can use the generated functions to retrieve a displayable instance at any aspect ratio or size. If the name of the image map is images, the following functions are generated:

  • display_image/4 - Returns a displayable instance of the named image
  • display_images/3 - Returns all images associated with this model. The return values are displayable.
  • find_image/2 - Finds the image with the given name
  • delete_image/2 - Deletes the image with the given name
  • has_image?/2 - Returns true if there is an image with the given name
  • put_image/3 - Sets the image with the given name, replacing any existing image.
  • find_image/2 - Finds the image on this model with the given name. The returned image is not displayable

Image Lists

An image list is an ordered list of images,. Images in an image list are able to be retrieved, deleted and added by index

If the name of the image list is images, the following functions are generated:

  • display_image/4 - Returns a displayable image with the given index or nil if one doesn't exist.
  • display_images/3 - Returns all images in the image list at the given aspect ratio and height.
  • find_image/2 - Returns the image with the given index, if it exists and nil otherwise.
  • delete_image_at/2 - When applied to a changeset, deletes the image with the given index.
  • replace_image_at/3 - Sets the image with the given index on this image list. This will replace any image with the same index.
  • insert_image_at/3 - Inserts an image into the image list at the specified index. This will grow the list
  • image_at/2 - Finds the image in this image list with the given index. The returned image is not displayable.

Generated functions

Adding an image list or an image map to your model creates adds helper functions that let you modify the image containers as well as functions that generate images suitable for display. The generated functions are fully documented and have proper typespecs.

Saving new images

To create a new image from a Plug.Upload, pass it in the image argument to one of the generated put functions. The image will be saved to backend storage during the attached model's update.

for example

  def save_avatar(%User{} = user, %Plug.Upload{} = image) do
    user
    |> User.changeset(%{})
    |> User.put_image(:avatar, image)
    |> Repo.update()
  end

If the function completes correctly, the image will be persisted in the configured storage.

Deleting old images

Old images must be deleted after the transaction completes, as we can't be guaranteed that the model will be saved correctly. To delete old images, use an Ecto.Multi

  def replace_avatar(%User{} = user, %Plug.Upload{} = avatar) do
    old_image = User.find_image(user, :avatar)
    changeset = user
      |> User.changeset(%{})
      |> User.put_image(:avatar, avatar)
    Multi.new()
    |> Multi.update(:update_user, changeset)
    |> Multi.run(:delete_old_image, fn _, _ ->
      case Eakins.Storage.delete(user, old_image) do
        :ok -> {:ok, old_image}
        error -> error
    end)
    |> Repo.transaction()
    |> case do
      {:ok, %{update_user: user}} ->
        {:ok, user}

      {: error, _failed_op, failed_value, _} ->
        {:error, failed_value}
    end

Link to this section Summary

Link to this section Functions

Link to this macro

image_list(name)

View Source (macro)
Link to this macro

image_map(name)

View Source (macro)