如何改变Ecto关系

时间:2016-04-12 19:53:21

标签: elixir phoenix-framework ecto

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

假设我有关系模型:

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

使用preload查询:

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

使用列表字段%PhoenixApp.Topic{...}

获取地图topic_meta

我希望在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

2 个答案:

答案 0 :(得分:1)

如果您想要更新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的一个。

答案 1 :(得分:0)

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

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