在Ecto中更新数组

use*_*962 1 elixir

我有以下型号:

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

        timestamps()
    end

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

我无法弄清楚如何从我的控制器更新subscriptions-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)
Run Code Online (Sandbox Code Playgroud)

我尝试过以下方法:

changeset = User.changeset(user, %{subscriptions: ["test"]})
Run Code Online (Sandbox Code Playgroud)

这会为数组添加"test",但如果我添加另一个值,它将被替换.

谢谢!

Dog*_*ert 8

由于您已经加载了旧值,因此最简单的方法是将值附加到旧列表并将其传递给User.changeset/2:

User.changeset(user, %{subscriptions: user.subscriptions ++ ["test"]})
Run Code Online (Sandbox Code Playgroud)

Ecto还支持push可以将项目推送到数组而不必使用加载旧值的操作Repo.update.此功能在此处记录.例:

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

要么

from(u in User, where: u.id == 123, update: [push: [subscriptions: "test"]])) |>
  Repo.update_all([])
Run Code Online (Sandbox Code Playgroud)