AJP
AJP

Reputation: 545

Elixir/Phoenix - trouble updating belongs_to association after it has been set

I have an app in which a user can belong to a group. Users and groups can be created separately, and a user can be added to a group later on.

The code below works fine the first time a user is added to a group:

User Model

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

User Controller

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

The data attribute for the above looks like this:

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

The problem is that if I try and change the group that that user belongs to, the update function returns 200 OK, but the group does not change.

Checking the output of the data variable shows that the group id is different in the request payload.

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

Why would the changeset not recognize the updated group id?

Upvotes: 0

Views: 1050

Answers (1)

AJP
AJP

Reputation: 545

I was using the incorrect value for on_replace in the model. It needed to be nilify instead of update.

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

Upvotes: 0

Related Questions