Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update array in Ecto

Tags:

elixir

I have the following model:

 schema "users" do
        field :email, :string
        field :subscriptions, {:array, :string}

        timestamps()
    end

    def changeset(struct, params \\ %{}) do
        struct
        |> cast(params, [:email,:subscriptions])
    end

I cant figure out how to update the subscriptions-array from my controller. Im looking to simply push a new string to the array:

def subscribe(conn, %{"category" => category} ) do
        IO.puts category # Will print "whatever_category"
        user = Repo.get(User, conn.assigns.user.id)
        changeset = User.changeset(user, ?)
        Repo.update(changeset)

I've tried the following:

changeset = User.changeset(user, %{subscriptions: ["test"]})

This adds "test" to the array but will get replaced if I add another value.

Thank you!

like image 845
user2915962 Avatar asked Aug 31 '25 22:08

user2915962


1 Answers

Since you've got the old value already loaded, the easiest way would be to append the value to the old list and pass that to User.changeset/2:

User.changeset(user, %{subscriptions: user.subscriptions ++ ["test"]})

Ecto also supports the push operation which can push an item to an array without having to load the old value in, using Repo.update. This feature is documented here. Example:

from(u in User, where: u.id == 123) |>
  Repo.update_all(push: [subscriptions: "test"])

or

from(u in User, where: u.id == 123, update: [push: [subscriptions: "test"]])) |>
  Repo.update_all([])
like image 63
Dogbert Avatar answered Sep 04 '25 21:09

Dogbert