drapermd

drapermd

Dynamic nested model in embeded field

Hello there!

I’m having a devil of a time getting a dynamic embedded schema to save in postgres.

So I started here, basically
https://github.com/elixir-ecto/ecto/pull/2113#issuecomment-412829999

But my core problem is that despite several iterations, when it goes to save it to the database, it throws

(UndefinedFunctionError) function :map.schema/1 is undefined (module :map is not available)

So in my hunt, I came across this package and it slimmed down the code, but I still have the same problem :(. It’s like ecto isn’t seeing the type update before it goes into schema. With your package the changeset automatically sets the type, which is really super nice, but for some reason I can’t get this to save to postgres:

## This is the latest iteration, of many attempts.

defmodule Geeks.Activities.Activity do
  @moduledoc false

  use Ecto.Schema
  import Ecto.Changeset
  import GatheringRole
  alias Geeks.Activities.Types

  embedded_schema do
    field :type, ActivityType
    field :title, :string
    field :max_participants, :integer
    field :next_start, :utc_datetime
    embeds_one :properties, :map
    embeds_many :rsvp, Geeks.Activities.ActivityRsvp
    embeds_many :history, Geeks.Activities.ActivityHistory do
      field :history_event, :string
      timestamps([types: :utc_datetime])
    end
    timestamps([types: :utc_datetime])
  end


  @all_fields ~w(type title max_participants next_start)a
  @required_fields ~w(type title)a
  defp properties_type(props_schema) do
    {:embed,
      %Ecto.Embedded{
        cardinality: :one,
        field: :properties,
        on_cast: &props_schema.changeset(&1, &2),
        on_replace: :update,
        owner: nil,
        related: props_schema,
        unique: true
      }}
  end

  def create_changeset(%{ properties: props } = params) do
    {:ok, props_schema} = Types.get_schema(:ttrpg)
    props_cs = EctoMorph.generate_changeset(props, props_schema)
    case props_cs.valid? do
      true ->
        changeset =
          %__MODULE__{}
          |> cast(params, @required_fields)
          |> Map.update!(:types, &Map.put(&1, :properties, properties_type(props_schema)))
          |> cast_embed(:properties)
          |> validate_required(@required_fields)
      false ->
        props_cs
    end


  end

  def create_changeset(%{} = params ) do
    create_changeset(%{params | properties: %{}})
  end

end

And elsewhere, in the context:

  def add_activity(%Gathering{ activities: activities} = gathering, activity_params \\ %{properties: %{}}) do
   changeset = Ecto.Changeset.change(gathering)
   activity = Geeks.Activities.Activity.create_changeset(activity_params)
   case activity.valid? do
     true -> changeset = Ecto.Changeset.put_embed(changeset, :activities, activities ++ [activity])
             |> Geeks.Repo.update!
     false -> {:error, activity}
   end

I did see this post: How to validate dynamic fields in embedded_schema - #4 by LostKobrakai

But it just seems like I’m missing something

I’m going to try to cross-post this to the elixir forums, but man it’s a brainweaver!

Where Next?

Popular in Questions Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

Other popular topics Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 44265 214
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement