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})
8.4) Changesets allow filtering, casting, validation and definition of constraints when manipulating structs. There is an example of working with changesets in the introductory documentation in the Ecto module. The functions cast/4 and change/2 are the usual entry points for creating changesets.
Ecto is the go-to database toolkit in the Elixir ecosystem, usually used to interact with SQL databases like Postgres and MySQL. It is very powerful and can be used for all the interaction with databases you need, such as inserting, validating, changing, and querying data. It has four main components: Schema.
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})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With