Please consider the following schema:
schema "businesses" do
...
has_many :contacts, Contact
has_many :conversations, Conversation
...
end
schema "contacts" do
...
belongs_to :business, Business
has_one :conversation, Conversation
...
end
schema "conversations" do
...
belongs_to :business, Business
belongs_to :contact, Contact
has_many :messages, Message
...
end
schema "messages" do
belongs_to :conversation, Conversation
belongs_to :contact, Contact
end
Given that I have a business
struct, how would I create the contact
, conversation
and message
structs in a way that handles associations?
The following works when excluding the messages
part.
business
|> Ecto.build_assoc(
:contacts,
%Contact{name: name, phone: phone}
)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(
:conversation,
%Conversation{business: business}
|> Ecto.Changeset.change()
|> Ecto.Changeset.cast_assoc(:business)
)
# |> Ecto.Changeset.put_assoc(:messages, [%Message{body: "hello"}])
|> Repo.insert()
With the second to last line uncommented, PostgreSQL is letting me know that message
should have a conversation_id
and that is true. How could that be set?
Adding an IO.inspect()
:
business
|> Ecto.build_assoc(
:contacts,
%Contact{name: name, phone: phone}
)
|> Ecto.Changeset.change()
|> Ecto.Changeset.put_assoc(
:conversation,
%Conversation{business: business}
|> Ecto.Changeset.change()
|> Ecto.Changeset.cast_assoc(:business)
)
|> IO.inspect()
# |> Ecto.Changeset.put_assoc(:messages, [%Message{body: "hello"}])
|> Repo.insert()
shows that we're working with the following changeset right before attempting to set the messages
association:
#Ecto.Changeset<
action: nil,
changes: %{
conversation: #Ecto.Changeset<action: :insert, changes: %{}, errors: [],
data: #Conversation<>, valid?: true>
},
errors: [],
data: #Contact<>,
valid?: true
Is there a way for the newly created message
to become associated with both the newly created contact
and the newly created conversation
?
This is doable with Ecto.Multi
.