Retrieving Id by building ecto association using Ecto.build_assoc

Hello all, please I don’t know where I’m getting it wrong, I have written the codes in many ways but I still can’t insert the parameters into the database. My main issue is the Ecto.build_assoc, I’m using it because I want to build an association of all books with the author. If I remove it, I can successfully insert new parameters into the database but the author Id will be nil.

This is my changeset

def changeset(book, attrs) do
author = Repo.get(Author, attrs["author_id"])
book 
|> cast(attrs, [:name, :description])
|> validate_required([:name, :description])   
|> Ecto.build_assoc(author)

end

This gives me this error:

(exit) an exception was raised:
** (UndefinedFunctionError) function Ecto.Changeset.__schema__/2 is undefined or private
    (ecto) Ecto.Changeset.__schema__(:association, %App.Authors.Author{__meta__: 
#Ecto.Schema.Metadata<:loaded, "authors">, gender: "female", description: "advanced author", id: 1, 
inserted_at: ~N[2018-11-06 16:44:22.938473], name: "Tonia", books: 
#Ecto.Association.NotLoaded<association :books is not loaded>, updated_at: ~N[2018-11-06 
16:44:22.944579]})
    (ecto) lib/ecto/association.ex:131: Ecto.Association.association_from_schema!/2
    (ecto) lib/ecto.ex:465: Ecto.build_assoc/3

I have to preload ‘:pairs’ but got a different error

 an exception was raised:
** (MatchError) no match of right hand side value: #Ecto.Changeset<action: nil, changes: %{description: 
"Bobby Bear", name: "Bobby Bear Novel"}, errors: [], data: #App.Books.Book<>, valid?: true>
    (app) lib/app/books/book.ex:28: App.Books.Book.changeset/2
    (app) lib/app/books/book.ex:62: App.Books.create_book/1

This is my code when I preload, so I’m sure I’m not preloading it the right way

def changeset(book, attrs) do
author = Repo.get(Author, attrs["author_id"])
book 
|> cast(attrs, [:name, :description])
|> validate_required([:name, :description]) 
|> Repo.preload(:books)  
|> Ecto.build_assoc(author)

end

I know there are a lot of errors on that code, can someone show me the right way the code should look? I just need to build an association with author inorder to get author_id before inserting to the database.

I think the error is that you’re not passing the name of the association to Ecto.build_assoc/3.

def changeset(book, attrs) do
  author = Repo.get(Author, attrs["author_id"])

  book 
  |> cast(attrs, [:name, :description])
  |> validate_required([:name, :description])   
  |> Ecto.build_assoc(author)
  #                  ^~~~~~~~
end

Try to see if this works:

def changeset(book, attrs) do
  author = Repo.get(Author, attrs["author_id"])

  book 
  |> cast(attrs, [:name, :description])
  |> validate_required([:name, :description])   
  |> Ecto.build_assoc(:authors, author)
  #                   ^~~~~~~~~~~~~~~~~
end
1 Like