Skip to content

embeds_one won't dump; says it's an invalid type #165

@jdewar

Description

@jdewar

I am trying sqlite3 out for the first time in Livebook. I believe that I have parity with how an app would use it, but I cannot get an embeds_one field to be inserted. I've appended an example of the failure on a 'buildings' table that has an embeds_one 'size' field. The error occurs in dump_field!:

(Ecto.ChangeError) value `%Satis.Model.BuildingSize{height: 0, length: 0, width: 0}` for `Satis.Model.Building.size` 
in `insert` does not match type #Ecto.Embedded<%Ecto.Embedded{cardinality: :one, field: :size, owner: 
Satis.Model.Building, related: Satis.Model.BuildingSize, on_cast: nil, on_replace: :raise, unique: true, ordered: true}>

I've used embeds before with postgres, and it feels like i'm missing something obvious, but I don't know what.
Below is the Livebook file (.livemd file not attachable).


embeds in sqlite3 won't dump

Mix.install([:kino, :ecto_sqlite3, {:ecto, "~> 3.12"}])

Section

sqlite3_db_file = "Documents/codex.sqlite3"

Application.put_env(:satis, Satis.Repo,
  # Cannot use :memory sqlite3 bc you can't migrate it
  database: sqlite3_db_file,
  # Turn off foreign key constraints to ease data importing
  foreign_keys: :off,
  log: false
)

defmodule Satis.Repo do
  @otp_app :satis
  use Ecto.Repo, otp_app: @otp_app, adapter: Ecto.Adapters.SQLite3
end

defmodule Satis.Model do
  defmacro __using__(_) do
    quote do
      use Ecto.Schema
      import Ecto.Changeset
      alias unquote(__MODULE__)
      @before_compile unquote(__MODULE__)
    end
  end

  defmacro __before_compile__(_) do
    quote do
      def changeset(params \\ %{}) do
        changeset(%__MODULE__{}, params)
      end

      def changeset(model, params) do
        fields = __MODULE__.__schema__(:fields)
        associations = __MODULE__.__schema__(:associations)
        embeds = __MODULE__.__schema__(:embeds)

        cs = cast(model, params, fields -- (embeds ++ associations))
        cs = Enum.reduce(embeds, cs, &cast_embed(&2, &1))
        Enum.reduce(associations, cs, &cast_assoc(&2, &1))
      end
    end
  end
end

defmodule Satis.Model.BuildingSize do
  use Satis.Model
  @primary_key false
  embedded_schema do
    field(:height, :integer)
    field(:length, :integer)
    field(:width, :integer)
  end
end

defmodule Satis.Model.Building do
  use Satis.Model
  @primary_key {:class_name, :string, autogenerate: false}
  schema "buildings" do
    embeds_one(:size, Model.BuildingSize)
  end

  defmodule Migration do
    use Ecto.Migration

    def change do
      create table("buildings", primary_key: false) do
        add(:class_name, :string, primary_key: true)
        add(:size, :map)
      end
    end
  end
end
{:module, Satis.Model.Building, <<70, 79, 82, 49, 0, 0, 61, ...>>,
 {:module, Satis.Model.Building.Migration, <<70, 79, 82, ...>>, {:change, 0}}}

Ready Database

alias Satis.Model
File.rm(sqlite3_db_file) |> dbg

Kino.start_child!(Satis.Repo) |> dbg

[
  Model.Building
]
|> Enum.with_index(1)
|> Enum.each(fn {migration, idx} ->
  :ok = Ecto.Migrator.up(Satis.Repo, idx, Module.concat([migration, "Migration"]))
end)
:ok
#PID<0.265.0>

09:42:48.019 [info] == Running 1 Satis.Model.Building.Migration.change/0 forward

09:42:48.021 [info] create table buildings

09:42:48.022 [info] == Migrated 1 in 0.0s
:ok
data =
  %{
    "class_name" => "Desc_QuarterPipeMiddleOutCorner_Ficsit_4x1_C",
    "size" => %{"height" => 0, "length" => 0, "width" => 0},
  }

Model.Building.changeset(data)
|> Satis.Repo.insert!()
** (Ecto.ChangeError) value `%Satis.Model.BuildingSize{height: 0, length: 0, width: 0}` for `Satis.Model.Building.size` in `insert` does not match type #Ecto.Embedded<%Ecto.Embedded{cardinality: :one, field: :size, owner: Satis.Model.Building, related: Satis.Model.BuildingSize, on_cast: nil, on_replace: :raise, unique: true, ordered: true}>
    (ecto 3.12.5) lib/ecto/repo/schema.ex:1115: Ecto.Repo.Schema.dump_field!/6
    (ecto 3.12.5) lib/ecto/repo/schema.ex:1124: anonymous fn/6 in Ecto.Repo.Schema.dump_fields!/5
    (stdlib 6.2) maps.erl:860: :maps.fold_1/4
    (ecto 3.12.5) lib/ecto/repo/schema.ex:1122: Ecto.Repo.Schema.dump_fields!/5
    (ecto 3.12.5) lib/ecto/repo/schema.ex:1055: Ecto.Repo.Schema.dump_changes!/7
    (ecto 3.12.5) lib/ecto/repo/schema.ex:406: anonymous fn/15 in Ecto.Repo.Schema.do_insert/4
    (ecto 3.12.5) lib/ecto/repo/schema.ex:1099: anonymous fn/3 in Ecto.Repo.Schema.wrap_in_transaction/6
    #cell:zrd25i7t5zceldyc:8: (file)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions