Elias Perez
Elias Perez

Reputation: 413

Arc and Arc_Ecto Storying Multiple images using :map field

Im trying to attach multiple images to a field. I could easily create an association to a images model, but I would like to see how could the same be accomplished with a map/array field.

The model looks as follows.

schema "users" do
  field :images, {:array}
end

def changeset(user, params \\ :invalid) do
  user
  |> cast(params, [:name])
  |> cast_attachments(params, [:avatar])
  |> validate_required([:name, :avatar])
end

Upvotes: 1

Views: 266

Answers (1)

Tiago Engel
Tiago Engel

Reputation: 3663

As far as I know using an array/map directly is not supported.

You could use and embedded schema to save it as a map though.

This should work:

defmodule Image do
  use Ecto.Schema      
  use Arc.Ecto.Schema

  import Ecto
  import Ecto.Changeset

  @required_fields ~w(file)
  @optional_fields ~w()

  embedded_schema do
    field :file, MyApp.UserImage.Type
  end

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)
    |> cast_attachments(params, [:file])
  end

end

defmodule User do
  use Ecto.Schema      

  import Ecto
  import Ecto.Changeset

  schema "projects" do
    field :code, :string
    embeds_many :images, MyApp.Image
  end

  def changeset(model, params \\ :empty) do
    model
    |> cast(params, @required_fields, @optional_fields)            
    |> cast_embed(:images) # invoke changeset in the embed module 
  end
end

And then you can use it like this

images = [%{file: "image1"}, %{file: "image2"}]
changeset = User.changeset(user, %{"images" => images})
new_user = Repo.update!(changeset)
urls = Enum.map new_user.images, fn image ->
  UserImage.urls({image.file, new_user})      
end

The only drawback is that you can't use the scope param in the UserImage module anymore when saving the images. This is because arc_ecto uses the model as the scope when you invoke cast_attachments function, and now you don't have the original model (User) when calling the function.

In the migration file you should define the images field to be a :map

Upvotes: 1

Related Questions