Patrick Goley
Patrick Goley

Reputation: 5417

Ecto model update multiple relationships

I'm trying to insert an Ecto model in the table worklogs which has two relationships user_id and issue_id. I find that when I try to create a changeset for a worklog with valid integers for these two fields, they are not included in the changeset and are null in the resulting worklog and API response. I've made sure that a user and issue exists with the primary keys I'm inserting with the worklog.

I've also looked at the documentation and it seems like build_assoc/3 is the way to update relationships, but it seems to be limited to inserting for a single relationship. From the docs, I think I should do something like this:

user = #get the user
worklog = Ecto.build_assoc(user, :worklogs, worklog_params)

But I've never declared worklogs on user, so how does it know to set user_id on the worklog? Also, how do I subsequently add the issue_id?

Schemas:

  schema "worklogs" do
    field :start_time, Ecto.DateTime
    field :end_time, Ecto.DateTime
    belongs_to :issue, MyApi.Issue
    belongs_to :user, MyApi.User

    timestamps()
  end

  schema "users" do
    field :name, :string

    timestamps()
  end

  schema "issues" do
    field :title, :string
    field :status, :string
    field :description, :string
    field :estimate, :float

    timestamps()
  end

Controller logic:

def create(conn, %{"worklog" => worklog_params}) do
    changeset = Worklog.changeset(%Worklog{}, worklog_params)

    IO.inspect changeset #user_id and issue_id are not present

    case Repo.insert(changeset) do
      {:ok, worklog} ->
        conn
        |> put_status(:created)
        |> put_resp_header("location", worklog_path(conn, :show, worklog))
        |> render("show.json", worklog: worklog)
      {:error, changeset} ->
        conn
        |> put_status(:unprocessable_entity)
        |> render(MyApi.ChangesetView, "error.json", changeset: changeset)
    end
  end

POST request:

{
  "worklog": {
    "start_time": "2017-04-08 02:20:00",
    "end_time": "2017-04-08 02:30:00",
    "issue_id": 1,
    "user_id": 1
  }
}

Upvotes: 0

Views: 572

Answers (2)

Steve Pallen
Steve Pallen

Reputation: 4507

Need to see your changeset to provide a concrete answer. However, I suspect your missing user_id and issue_id in the cast call in your changeset. Ecto will not add fields to the changes if the fields are not listed in the cast list.

The phoenix model generator does not add belongs_to fields to the cast operation. I usually add them manually.

Upvotes: 1

Justin Wood
Justin Wood

Reputation: 10041

In this case of multiple relations needing to be set, it is probably better to just set them explicitly like this

%Worklog{user_id: user.id, issue_id: issue.id}
|> Worklog.changset(worklog_params)
|> Repo.insert()

You may also benefit from putting relations onto your user and issue schemas so that you are able to easier query for the worklogs that relate to a given user or issue.

Upvotes: 1

Related Questions