Elixir 成功更新Repo.update后,异位重新加载属于关联

Elixir 成功更新Repo.update后,异位重新加载属于关联,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,通过params中的parent\u id将给定的child的关联从parent\u a更改为parent\u b,会留下一条过时的记录。parent对象 e、 g.(假设参数匹配%{child:%{id:'1',parent_id:'6'}) 更新后检索新关联的父记录的正确方法是什么?目前在EXTO中没有内置的方法。您还存在无法使用预加载的问题,因为关联已预加载 一个选择是: %{child | parent: Repo.get!(Parent, child.parent_id)} 您还可以

通过params中的
parent\u id
将给定的
child
的关联从
parent\u a
更改为
parent\u b
,会留下一条过时的
记录。parent
对象

e、 g.(假设参数匹配
%{child:%{id:'1',parent_id:'6'}


更新后检索新关联的父记录的正确方法是什么?

目前在EXTO中没有内置的方法。您还存在无法使用预加载的问题,因为关联已预加载

一个选择是:

%{child | parent: Repo.get!(Parent, child.parent_id)}

您还可以选择在调用
Repo.update
之前不调用预加载,这将阻止关联已加载。

强制预加载。默认情况下,Ecto不会预加载已加载的关联

child
|> Child.changeset(params)
|> Repo.update!()
|> Repo.preload(:parent, force: true)
如果您想以不同的方式处理错误,也可以不使用bang更新

child
|> Child.changeset(params)
|> Repo.update()
|> case do
  {:ok, child} -> {:ok, Repo.preload(child, :parent, force: true)}
  error -> error
end
在一个更现实的错误处理示例中,它可能看起来像

with {:ok, child} <- get_child(child_id),
     {:ok, child} <- update_child(child, params) do
  # Do stuff
else
  {:error, %Ecto.Changeset{} = changeset} -> # Handle error
  {:error, reason} -> # Handle error
end

defp get_child(child_id) do
  case Repo.get(Child, child_id) do
    nil -> {:error, :not_found}
    child -> {:ok, child}
  end  
end

defp update_child(child, params) do
  updated_child = 
    child
    |> Child.changeset(params)
    |> Repo.update!()
    |> Repo.preload(:parent, force: true)
rescue
  error in Ecto.InvalidChangesetError -> {:error, error.changeset}
  error in RuntimeError -> {:error, error.message}
end
带有{:ok,child}#句柄错误
结束
defp get_child(child_id)do
案例回购get(儿童,儿童id)do
nil->{:错误,:未找到}
child->{:好的,child}
结束
结束
defp update_child(child,params)do
更新的\u子项=
小孩
|>子变更集(参数)
|>Repo.update!()
|>回购预加载(:父项,强制:真)
营救
exto.InvalidChangesetError中出错->{:error,error.changeset}
运行时错误->{:错误,错误。消息}
结束

使用Ecto 2.0,您现在可以将
force:true
传递到
Repo.preload
以强制重新加载已加载的关联。来源:@JonathanPerret值得把你的评论变成答案吗?在现代版本的EXTO中,这似乎是解决问题的惯用方法。
with {:ok, child} <- get_child(child_id),
     {:ok, child} <- update_child(child, params) do
  # Do stuff
else
  {:error, %Ecto.Changeset{} = changeset} -> # Handle error
  {:error, reason} -> # Handle error
end

defp get_child(child_id) do
  case Repo.get(Child, child_id) do
    nil -> {:error, :not_found}
    child -> {:ok, child}
  end  
end

defp update_child(child, params) do
  updated_child = 
    child
    |> Child.changeset(params)
    |> Repo.update!()
    |> Repo.preload(:parent, force: true)
rescue
  error in Ecto.InvalidChangesetError -> {:error, error.changeset}
  error in RuntimeError -> {:error, error.message}
end