Elixir / Phoenix - 设置后更新belongs_to关联有问题

时间:2017-12-11 12:54:15

标签: elixir phoenix-framework ecto

我有一个用户可以属于某个组的应用。可以单独创建用户和组,稍后可以将用户添加到组中。

以下代码在用户首次添加到群组时效果正常:

用户模型

use Ecto.Schema
import Ecto.Changeset

schema "users" do
  field :email, :string
  field :description, :string
  field :deleted, :boolean, default: false
  belongs_to :group, Admin.Group, foreign_key: :group_id, on_replace: :update

  timestamps()
end

def changeset(struct, params \\ %{}) do
  struct
  |> cast(params, [:code, :user_email, :description, :created_at, :deleted])
  |> validate_required([:code, :user_email, :created_at,])
end

用户控制器

def update(conn, %{"id" => id, "data" => data = %{"type" => "users", "attributes" => _user_params, "relationships" => relationships}}) do
  user = Repo.get!(User, id) |> Repo.preload :group
  group = Repo.get_by!(Group, id: data["relationships"]["group"]["data"]["id"])
  changeset = User.changeset(user, Params.to_attributes(data)) |> Ecto.Changeset.put_assoc(:group, group)
  case Repo.update(changeset) do
    {:ok, user} ->
      render(conn, "show.json-api", data: user)
    {:error, changeset} ->
      conn
      |> put_status(:unprocessable_entity)
      |> render(:errors, data: changeset)
  end
end

上面的数据属性如下所示:

%{"attributes" => %{"description" => nil, "inserted_at" => "2017-12-01T14:20:58.423Z",
    "updated_at" => "2017-12-11T10:36:24.073Z",
    "email" => "test@gmail.com"}, "id" => "292",
  "relationships" => %{"group" => %{"data" => %{"id" => "1",
        "type" => "groups"}}}, "type" => "users"}

问题是,如果我尝试更改该用户所属的组,则更新函数将返回200 OK,但该组不会更改。

检查数据变量的输出显示请求有效负载中的组ID不同。

%{"attributes" => %{"description" => nil, "inserted_at" => "2017-12-01T14:20:58.423Z",
    "updated_at" => "2017-12-11T10:36:24.073Z",
    "email" => "test@gmail.com"}, "id" => "292",
  "relationships" => %{"group" => %{"data" => %{"id" => "2",
        "type" => "groups"}}}, "type" => "users"}

为什么变更集无法识别更新的组ID?

1 个答案:

答案 0 :(得分:0)

我在模型中使用了on_replace的错误值。它必须是nilify而不是update

belongs_to :group, Admin.Group, foreign_key: :group_id, on_replace: :nilify