I apologize in advance if this is the wrong forum to ask this newbie phoenix/elixir question:
I’m trying to post/save changes from my front end to my Phoenix/Elixir back end of a model with a has_many relationship, each of which have a has_many relationship but It’s not saving.
Here are my three relevant models:
defmodule ContestDirectorApi.Roundscore do
use ContestDirectorApi.Web, :model
schema "roundscores" do
field :totalroundscore, :float
field :normalizedscore, :float
belongs_to :contestregistration, ContestDirectorApi.Contestregistration
belongs_to :round, ContestDirectorApi.Round
has_many :maneuverscores, ContestDirectorApi.Maneuverscore
timestamps
end
@required_fields ~w(totalroundscore normalizedscore)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
|> cast_assoc(:maneuverscores, required: true)
end
end
defmodule ContestDirectorApi.Maneuverscore do
use ContestDirectorApi.Web, :model
schema "maneuverscores" do
field :totalscore, :float
belongs_to :maneuver, ContestDirectorApi.Maneuver
belongs_to :roundscore, ContestDirectorApi.Roundscore
has_many :scores, ContestDirectorApi.Score
timestamps
end
@required_fields ~w(totalscore)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
|> cast_assoc(:scores, required: true)
end
end
defmodule ContestDirectorApi.Score do
use ContestDirectorApi.Web, :model
schema "scores" do
field :points, :float
belongs_to :maneuverscore, ContestDirectorApi.Maneuverscore
timestamps
end
@required_fields ~w(points)
@optional_fields ~w()
def changeset(model, params \\ :empty) do
model
|> cast(params, @required_fields, @optional_fields)
end
end
And my controller’s update method:
def update(conn, %{"id" => id, "data" => data = %{"type" => "roundscores", "attributes" => roundscore_params}}) do
roundscore = Repo.get!(Roundscore, id) |> Repo.preload(:maneuverscores) |> Repo.preload(:contestregistration)
changeset = Roundscore.changeset(roundscore, Params.to_attributes(data))
case Repo.update(changeset) do
{:ok, roundscore} ->
render(conn, "show.json", data: roundscore)
{:error, changeset} ->
conn
|> put_status(:unprocessable_entity)
|> render(ContestDirectorApi.ChangesetView, "error.json", changeset: changeset)
end
end
When I post my changes, the log shows:
[debug] Processing by ContestDirectorApi.RoundscoreController.update/2
Parameters: %{"data" => %{"attributes" => %{"normalizedscore" => 3214.29, "totalroundscore" => 45}, "id" => "13", "maneuverscores" => [%{"data" => %{"attributes" => %{"total-score" => 12}, "id" => "77", "relationships" => %{"maneuver" => %{"data" => %{"id" => "26", "type" => "maneuvers"}}, "roundscore" => %{"data" => %{"id" => "13", "type" => "roundscores"}}}, "scores" => [%{"data" => %{"attributes" => %{"points" => 1}, "id" => "244", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "77", "type" => "maneuverscores"}}}, "type" => "scores"}}, %{"data" => %{"attributes" => %{"points" => 4}, "id" => "245", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "77", "type" => "maneuverscores"}}}, "type" => "scores"}}, %{"data" => %{"attributes" => %{"points" => 7}, "id" => "246", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "77", "type" => "maneuverscores"}}}, "type" => "scores"}}], "type" => "maneuverscores"}}, %{"data" => %{"attributes" => %{"total-score" => 15}, "id" => "78", "relationships" => %{"maneuver" => %{"data" => %{"id" => "27", "type" => "maneuvers"}}, "roundscore" => %{"data" => %{"id" => "13", "type" => "roundscores"}}}, "scores" => [%{"data" => %{"attributes" => %{"points" => 2}, "id" => "247", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "78", "type" => "maneuverscores"}}}, "type" => "scores"}}, %{"data" => %{"attributes" => %{"points" => 5}, "id" => "248", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "78", "type" => "maneuverscores"}}}, "type" => "scores"}}, %{"data" => %{"attributes" => %{"points" => 8}, "id" => "249", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "78", "type" => "maneuverscores"}}}, "type" => "scores"}}], "type" => "maneuverscores"}}, %{"data" => %{"attributes" => %{"total-score" => 18}, "id" => "79", "relationships" => %{"maneuver" => %{"data" => %{"id" => "28", "type" => "maneuvers"}}, "roundscore" => %{"data" => %{"id" => "13", "type" => "roundscores"}}}, "scores" => [%{"data" => %{"attributes" => %{"points" => 3}, "id" => "250", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "79", "type" => "maneuverscores"}}}, "type" => "scores"}}, %{"data" => %{"attributes" => %{"points" => 6}, "id" => "251", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "79", "type" => "maneuverscores"}}}, "type" => "scores"}}, %{"data" => %{"attributes" => %{"points" => 9}, "id" => "252", "relationships" => %{"maneuverscore" => %{"data" => %{"id" => "79", "type" => "maneuverscores"}}}, "type" => "scores"}}], "type" => "maneuverscores"}}], "relationships" => %{"contestregistration" => %{"data" => %{"id" => "7", "type" => "contestregistrations"}}, "round" => %{"data" => %{"id" => "13", "type" => "rounds"}}}, "type" => "roundscores"}, "id" => "13"}
Pipelines: [:api]
[debug] SELECT r0."id", r0."totalroundscore", r0."normalizedscore", r0."contestregistration_id", r0."round_id", r0."inserted_at", r0."updated_at" FROM "roundscores" AS r0 WHERE (r0."id" = $1) [13] OK query=1.1ms
[debug] SELECT m0."id", m0."totalscore", m0."maneuver_id", m0."roundscore_id", m0."inserted_at", m0."updated_at" FROM "maneuverscores" AS m0 WHERE (m0."roundscore_id" IN ($1)) ORDER BY m0."roundscore_id" [13] OK query=0.5ms
[debug] SELECT c0."id", c0."pilotname", c0."contest_id", c0."pilotclass_id", c0."pilot_id", c0."inserted_at", c0."updated_at" FROM "contestregistrations" AS c0 WHERE (c0."id" IN ($1)) [7] OK query=1.1ms
any if I pry on the changeset in the controller, it says:
%Ecto.Changeset{action: nil,
changes: %{normalizedscore: 3214.29, totalroundscore: 45.0}, constraints: [],
errors: [], filters: %{},
model: %ContestDirectorApi.Roundscore{__meta__: #Ecto.Schema.Metadata<:loaded>,
contestregistration: %ContestDirectorApi.Contestregistration{__meta__: #Ecto.Schema.Metadata<:loaded>,
contest: #Ecto.Association.NotLoaded<association :contest is not loaded>,
contest_id: 1, id: 7, inserted_at: #Ecto.DateTime<2016-06-06T22:41:27Z>,
pilot: #Ecto.Association.NotLoaded<association :pilot is not loaded>,
pilot_id: 3,
pilotclass: #Ecto.Association.NotLoaded<association :pilotclass is not loaded>,
pilotclass_id: 1, pilotname: "Dan Monroe",
roundscores: #Ecto.Association.NotLoaded<association :roundscores is not loaded>,
updated_at: #Ecto.DateTime<2016-06-06T22:41:27Z>}, contestregistration_id: 7,
id: 13, inserted_at: #Ecto.DateTime<2016-06-06T22:47:15Z>,
maneuverscores: [%ContestDirectorApi.Maneuverscore{__meta__: #Ecto.Schema.Metadata<:loaded>,
id: 77, inserted_at: #Ecto.DateTime<2016-06-06T22:47:15Z>,
maneuver: #Ecto.Association.NotLoaded<association :maneuver is not loaded>,
maneuver_id: 26,
roundscore: #Ecto.Association.NotLoaded<association :roundscore is not loaded>,
roundscore_id: 13,
scores: #Ecto.Association.NotLoaded<association :scores is not loaded>,
totalscore: 0.0, updated_at: #Ecto.DateTime<2016-06-06T22:47:15Z>},
%ContestDirectorApi.Maneuverscore{__meta__: #Ecto.Schema.Metadata<:loaded>,
id: 78, inserted_at: #Ecto.DateTime<2016-06-06T22:47:15Z>,
maneuver: #Ecto.Association.NotLoaded<association :maneuver is not loaded>,
maneuver_id: 27,
roundscore: #Ecto.Association.NotLoaded<association :roundscore is not loaded>,
roundscore_id: 13,
scores: #Ecto.Association.NotLoaded<association :scores is not loaded>,
totalscore: 0.0, updated_at: #Ecto.DateTime<2016-06-06T22:47:15Z>},
%ContestDirectorApi.Maneuverscore{__meta__: #Ecto.Schema.Metadata<:loaded>,
id: 79, inserted_at: #Ecto.DateTime<2016-06-06T22:47:15Z>,
maneuver: #Ecto.Association.NotLoaded<association :maneuver is not loaded>,
maneuver_id: 28,
roundscore: #Ecto.Association.NotLoaded<association :roundscore is not loaded>,
roundscore_id: 13,
scores: #Ecto.Association.NotLoaded<association :scores is not loaded>,
totalscore: 0.0, updated_at: #Ecto.DateTime<2016-06-06T22:47:15Z>}],
normalizedscore: 1076.92,
round: #Ecto.Association.NotLoaded<association :round is not loaded>,
round_id: 13, totalroundscore: 14.0,
updated_at: #Ecto.DateTime<2016-06-07T16:56:25Z>}, optional: [], opts: [],
params: %{"contestregistration_id" => "7", "normalizedscore" => 3214.29,
"round_id" => "13", "totalroundscore" => 45, "type" => "roundscores"},
prepare: [], repo: nil,
required: [:maneuverscores, :totalroundscore, :normalizedscore],
types: %{contestregistration_id: :id, id: :id, inserted_at: Ecto.DateTime,
maneuverscores: {:assoc,
%Ecto.Association.Has{cardinality: :many, defaults: [],
field: :maneuverscores, on_cast: :changeset, on_delete: :nothing,
on_replace: :raise, owner: ContestDirectorApi.Roundscore, owner_key: :id,
queryable: ContestDirectorApi.Maneuverscore,
related: ContestDirectorApi.Maneuverscore, related_key: :roundscore_id}},
normalizedscore: :float, round_id: :id, totalroundscore: :float,
updated_at: Ecto.DateTime}, valid?: true, validations: []}
with a result that it does not save my changes to maneuverscores or scores.
I would really appreciate it if someone could point me in the right direction on how to save my relationship data for both relationships at the same time.
Thanks,
Dan