如何更新Ecto中的一对多关联

时间:2016-10-11 15:22:52

标签: elixir phoenix-framework ecto

在我的应用中,我在节目和剧集之间有一对多的关系。节目可以有很多剧集。在创建剧集时,我可以通过这样做来建立与节目的关联:

  def create(conn, %{"episode" => episode_params}) do
    show = Repo.get!(Show, episode_params["show_id"])
    changeset =
      show
      |> build_assoc(:episodes)
      |> Episode.changeset(episode_params)

    case Repo.insert(changeset) do
      {:ok, _post} ->
        conn
        |> put_flash(:info, "Episode created successfully.")
        |> redirect(to: show_path(conn, :show, show))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

如何最好地将剧集关联更新为演出?这就是我现在所拥有的。

  def update(conn, %{"id" => id, "episode" => episode_params}) do
    episode = Repo.get!(Episode, id)
    changeset = Episode.changeset(episode, episode_params)

    case Repo.update(changeset) do
      {:ok, episode} ->
        conn
        |> put_flash(:info, "Episode updated successfully.")
        |> redirect(to: episode_path(conn, :show, episode))
      {:error, changeset} ->
        render(conn, "edit.html", episode: episode, changeset: changeset)
    end
 end

1 个答案:

答案 0 :(得分:2)

除非您有一些要求,例如不允许对某些操作进行show_id更改,否则最简单的方法是将show_id添加到cast调用中的允许字段列表中Episode.changeset/2,并让数据库使用外键约束处理无效的show_id值。

defmodule MyApp.Episode
  ...
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:show_id, ...]) # add :show_id here
  end
end

然后直接将episode_params传递给changesetcreate中的update

def create(conn, %{"episode" => episode_params}) do
  changeset = Episode.changeset(%Episode{}, episode_params)
  ...
end
def update(conn, %{"id" => id, "episode" => episode_params}) do
  episode = Repo.get!(Episode, id)
  changeset = Episode.changeset(episode, episode_params)
  ...
end

确保您的迁移使用show_id添加了references(...)字段,或者您手动添加了数据库约束。类似的东西:

create table(:episodes) do
  ...
  add :show_id, references(:shows, on_delete: :nothing)
  ...
end