I am a bit stuck in how to actually set an association with a changeset. I have this code in my model:
defmodule MyApp.MemberApplication do
use MyApp.Web, :model
use Ecto.Schema
use Arc.Ecto.Schema
alias MyApp.Repo
alias MyApp.MemberApplication
schema "applications" do
field :name, :string
field :email, :string
field :time_accepted, Ecto.DateTime
field :time_declined, Ecto.DateTime
belongs_to :accepted_by, MyApp.Admin
belongs_to :declined_by, MyApp.Admin
timestamps()
end
def set_accepted_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:time_accepted, :accepted_by_id])
|> cast_assoc(params, :accepted_by)
|> set_time_accepted
end
defp set_time_accepted(changeset) do
datetime = :calendar.universal_time() |> Ecto.DateTime.from_erl
put_change(changeset, :time_accepted, datetime)
end
end
I want to save an association to the Admin
that performed a certain operation (accepting or declining an member_application) and a timestamp. The generation of the timestamp works but when I try to save an association I always get the error
** (FunctionClauseError) no function clause matching in Ecto.Changeset.cast_assoc/3
This is how I want to set the association:
iex(26)> application = Repo.get(MemberApplication, 10)
iex(27)> admin = Repo.get(Admin, 16)
iex(28)> changeset = MemberApplication.set_accepted_changeset(application, %{accepted_by: admin})
Thanks @Dogbert. This is how I got it to work
defmodule MyApp.MemberApplication do
use MyApp.Web, :model
use Ecto.Schema
use Arc.Ecto.Schema
alias MyApp.Repo
alias MyApp.MemberApplication
schema "applications" do
field :name, :string
field :email, :string
field :time_accepted, Ecto.DateTime
field :time_declined, Ecto.DateTime
belongs_to :accepted_by, MyApp.Admin
belongs_to :declined_by, MyApp.Admin
timestamps()
end
def set_accepted_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:time_accepted, :accepted_by_id])
# Change cast_assoc
|> cast_assoc(:accepted_by)
|> set_time_accepted
end
defp set_time_accepted(changeset) do
datetime = :calendar.universal_time() |> Ecto.DateTime.from_erl
put_change(changeset, :time_accepted, datetime)
end
end
And then preload the association and set the ID directly. Or do it directly in the query:
iex(26)> application = Repo.get(MemberApplication, 10)
iex(27)> application = Repo.preload(application, :accepted_by)
iex(28)> admin = Repo.get(Admin, 16)
iex(29)> changeset = MemberApplication.set_accepted_changeset(application, %{accepted_by_id: admin.id})