如何改变 Ecto 关系

How to change Ecto relationships

我是 Elixir 的新手,正在寻找如何在 Ecto 模型中改变关系的正确方法。

假设我有关系模型:

 schema "topic" do
      has_many :topic_meta, PhoenixApp.TopicMeta

并使用预加载查询:

 topic = from t in query,
        left_join: meta in assoc(t, :topic_meta),
        preload: [topic_meta: meta] 
        |> Repo.one

使用列表字段 topic_meta

获取地图 %PhoenixApp.Topic{...}

我想更改 topic_meta 个字段之一的值:

 changed_meta = %{List.first(topic.topic_meta) | last_read: "newValue"}

问题:

如何从我的查询中插入已更改的 topic_meta 关系提交给 topic?使更新字段的新查询看起来没有必要。

更新详情:

first_meta = List.first(topic.topic_meta) // this is first meta

result =  Repo.update!(PhoenixApp.Topic.changeset(first_meta, %{last_read: "newValue"}))

case result do
  {:ok, topic_meta}        ->  
 // topic_meta successfully updated, but topic does not contain this model
end

使用build_assochttps://hexdocs.pm/ecto/Ecto.html#build_assoc/3

changed_meta = Ecto.build_assoc(topic, :topic_meta, last_read: "newValue")
Repo.insert!(comment)

如果您的 changed_meta 形状想要更新,您应该使用 Repo.update/2:

Repo.update(changed_meta)

希望对您有所帮助!

更新

如果您想在 topic 中看到更新的元素而不重新加载它,您可以手动替换 topic_meta 的当前列表。

鉴于您已经准备好 change_meta,您可以执行以下操作:

index = Enum.find_index(topic.topic_meta &(&1.id == changed_meta.id))
list  = List.replace_at(topic.topic_meta, index, changed_meta)
topic = %{topic | topic_meta: list}

这样,最后一行的 topic 将更新 topic_meta 列表,其中包含 changed_meta.