user1156168
user1156168

Reputation: 956

How to change Ecto relationships

I'm a new in Elixir and looking for proper way of how to chanage relationship in Ecto model.

Assume I have model with relationship:

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

And query with preload:

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

Get map %PhoenixApp.Topic{...} with list field topic_meta

I want change value in one of topic_meta fields:

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

Question:

How to insert changed topic_meta relation filed to topic from my query? Make a new query for updating fields looks like unnecessary.

Update in details:

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

Upvotes: 0

Views: 513

Answers (2)

Paweł Dawczak
Paweł Dawczak

Reputation: 9639

If you have your changed_meta in shape you want to update, you should use Repo.update/2:

Repo.update(changed_meta)

Hope that helps!

Update

If you want to see element updated in your topic without reloading it, you could replace current list of topic_meta manually.

Given you have prepared change_meta, you could do something like:

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}

With this, the topic from the last line will have updated list of topic_meta, containing the one of changed_meta.

Upvotes: 1

Alex Troush
Alex Troush

Reputation: 677

Use 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)

Upvotes: 0

Related Questions