I cannot figure out what could be wrong here I copied the code directly from the many_to_many docs.
def highlight_verses(verse_ids, member) do
verses = get_verses(verse_ids)
loaded =
member
|> Repo.preload(:highlights)
loaded
|> Changeset.change()
|> Changeset.put_assoc(:highlights, [verses | loaded.highlights])
|> Repo.update()
end
Here is the association
schema "members" do
field :email, :string
field :password, :string, virtual: true, redact: true
field :hashed_password, :string, redact: true
field :confirmed_at, :naive_datetime
field :first_name, :string
field :last_name, :string
field :accepted_terms_at, :naive_datetime
field :accepted_privacy_at, :naive_datetime
has_many :account_members, WithoutCeasing.Identity.AccountMember, on_delete: :delete_all
has_many :accounts, through: [:account_members, :accounts]
has_many :resources, WithoutCeasing.Content.Resource
has_many :notes, WithoutCeasing.Content.Note
many_to_many :highlights, WithoutCeasing.Bible.Verse,
join_through: "highlights",
on_replace: :delete
timestamps()
end
Any ideas?
Probably too obvious a question but still: are verses
and member.highlights
containing collections of the same structs?
Yes! Sorry here is the other side
schema "verses" do
field :book, :string
field :chapter, :integer
field :verse, :integer
has_many :verse_revisions, WithoutCeasing.Bible.VerseRevision
many_to_many :members, WithoutCeasing.Identity.Member,
join_through: "highlights",
on_replace: :delete
many_to_many :notes, WithoutCeasing.Content.Note,
join_through: "verse_notes",
on_replace: :delete
many_to_many :resources, WithoutCeasing.Content.Resource,
join_through: "verse_resources",
on_replace: :delete
end
Nothing immediately springs to mind, sorry. Have you tried IO.inspect
-ing both verses
and member.highlights
before the Changeset.put_assoc
call?
As far as I can tell they both look good. One is an empty array and the other is an array with one %Verse{} struct. Here is more of the stack trace:
** (FunctionClauseError) no function clause matching in anonymous fn/2 in Ecto.Changeset.get_changed/6
(ecto 3.7.1) lib/ecto/changeset.ex:406: anonymous fn(%WithoutCeasing.Bible.Verse{__meta__: #Ecto.Schema.Metadata<:loaded, "verses">, book: "john", chapter: 12, id: 43012001, members: #Ecto.Association.NotLoaded<association :members is not loaded>, notes: #Ecto.Association.NotLoaded<association :notes is not loaded>, resources: #Ecto.Association.NotLoaded<association :resources is not loaded>, verse: 1, verse_revisions: #Ecto.Association.NotLoaded<association :verse_revisions is not loaded>}, {%{}, [], true}) in Ecto.Changeset.get_changed/6
(elixir 1.12.0) lib/enum.ex:2356: Enum."-reduce/3-lists^foldl/2-0-"/3
(ecto 3.7.1) lib/ecto/changeset.ex:400: Ecto.Changeset.change/2
(ecto 3.7.1) lib/ecto/changeset/relation.ex:202: Ecto.Changeset.Relation.do_change/4
(ecto 3.7.1) lib/ecto/changeset/relation.ex:351: Ecto.Changeset.Relation.map_changes/9
(ecto 3.7.1) lib/ecto/changeset/relation.ex:165: Ecto.Changeset.Relation.change/3
(ecto 3.7.1) lib/ecto/changeset.ex:1222: Ecto.Changeset.put_change/7
(ecto 3.7.1) lib/ecto/changeset.ex:1432: Ecto.Changeset.put_relation/5
(without_ceasing 0.1.0) lib/without_ceasing/bible.ex:51: WithoutCeasing.Bible.highlight_verses/2
Can you show the exact offending line? Or re-repost a code snippet and point at line 51?
al2o3cr
7
This is likely the problem - doing this results in a list where the first element is a list of Verse
structs.
The example in put_assoc
uses [ | ]
, but to add a single comment.
verses ++ loaded.highlights
would give a flat list.
1 Like