2016-04-12 2 views
0

Я новый в Эликсире и ищу правильный способ взаимодействия отношений в модели Ecto.Как изменить отношения 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 

Получить карту %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 

ответ

1

Если у вас есть ваши changed_meta в форму, которую вы хотите обновить, вы должны использовать Repo.update/2:

Repo.update(changed_meta) 

Надеюсь, что это поможет!

Update

Если вы хотите, чтобы увидеть элемент обновлен в вашем 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.

+0

Спасибо за ваш ответ. Я подробно изложил вопрос в разделе «Обновление в деталях». Вопрос заключался в том, как объединить результат «Repo.update» с исходными данными. – user1156168

+0

О! Я вижу, о чем вы спрашиваете. Боюсь, что нет «простого» способа сделать это из-за неизменности. «тема» не похожа на объекты (например, на Ruby/Java), поэтому такое изменение не сразу отражается. Самый простой способ отразить это - просто перезагрузить данные из базы данных. Здесь деление на действия в Phoenix имеет смысл - вы обновляете значения в действии «update» и перенаправляете пользователя на сортировку действия «show», где обновленные данные извлекаются из БД. –

+0

Эй @ user1156168 - пожалуйста, взгляните на обновленный ответ. Код довольно многословный (по сравнению с тем, что у вас было бы, если бы вы делали подобное в языке OO), но он должен делать то, что вы ожидаете. Надеюсь, что это немного прояснит проблему! –

0

Использование build_assochttps://hexdocs.pm/ecto/Ecto.html#build_assoc/3

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

Дело ясно для нового 'topic_meta', но waht делать, когда уже заданы ассоциации. – user1156168