How/where 在 Phoenix 1.3 中预加载 has_many 关系数据

How/where to preload has_many relationship data in Phoenix 1.3

我正在学习 Elixir/Phoenix 示例项目并开始使用 Phoenix 1.2。 现在,我使用 Phoenix 1.3 重新创建了项目以 see/learn 差异并调整我的旧代码。

在那里我有模型 PositionSkill 之间的 has_many 关系。而在 position_controller.ex 的 1.2 代码中我使用了

case Repo.insert(changeset) do
  {:ok, position} ->
    position = position |> Repo.preload(:skills)
    ...

预加载 skills 以进行渲染 我不确定将它放在我的 1.3 代码中的什么位置。

Controller 现在似乎是错误的地方(Repo 甚至不知道)所以我把它放在 create_position 的上下文文件中,如下所示:

def create_position(attrs \ %{}) do
  with {:ok, %Position{} = position} <-
    %Position{}
    |> Position.changeset(attrs)
    |> Repo.insert() do

    position = Repo.preload(position, :skills)
    {:ok, position}
  end
end

这感觉很奇怪,因为它现在不仅仅是插入。

那么执行此任务的正确和最佳方法是什么?

您将希望根据您的上下文/应用程序的外观将内容分开。

def insert_position(attrs) do
  attrs
  |> changeset()
  |> MyApp.Repo.insert()
end

如果技能和职位处于相同的上下文中,您可以按照

的方式做一些事情
def load_skills(position) do
  MyApp.Repo.preload(position, :skills)
end

如果是在单独的上下文中,可以进行以下操作

def get_skills_for_position(position) do
  # I'm not sure which way you have the relationship
  MyApp.Repo.all(from skill in MyApp.Skill, 
    join: position in MyApp.Position,
    on: skill.id == position.skill_id)
end

然后,在你的控制器中,由你来把这些东西放在一起。

def create(conn, %{"position" => position_attrs}) do
  case create_position(position_attrs) do
    {:ok, position} ->
      # or load_skills_for_position, depending if they are in the same contexts.
      position = load_skills(position) 
      ...
    {:error, changeset} ->
      ...
  end
end