Can I create a schema without a table?

Hello I want to create multiple entries,

I can create a schema like

has_many :something, X

and then

cast_assoc(:something, x/2)

but I don’t need a table in the DBMS for this, this should be like a virtual schema

https://hexdocs.pm/ecto/embedded-schemas.html

1 Like

embedded schemas are inside other schemas, which schema should I embed it in?

You can embed them in other schemas but you can also use them on their own. i.e. this example:

defmodule UserProfile do
  use Ecto.Schema

  embedded_schema do
    field :online, :boolean
    field :dark_mode, :boolean
    field :visibility, Ecto.Enum, values: [:public, :private, :friends_only]
  end
end

You can define a changeset function in this module as well for validation.

3 Likes

wow, it works, thanks

1 Like

There is an issue I can not insert the cast_assoc into the database, the error message is:

X needs to be a schema with source

after running

X.changeset(%X{} |> Repo.preload(:something), %{something: [%{data: :x}]}) |> Repo.insert

Oh maybe I misunderstood your question. So are you saying you have an embedded schema and one of the fields of the embedded schema is an association that needs to be persisted to the database?

1 Like

one of the fields of the embedded schema is an association that needs to be persisted to the database

yes that is it

You would have to work with the associated changeset/struct alone in that case. Anytime you try to insert a struct or a changeset, it must be based on a schema that is backed by a table.

Sorry if I’m not understanding your example. But it looks like you will take your embedded schema, preload the associations (basically fetch them from the db) and then do something to the association and then insert it back into the db?

If this is the correct, you could do this:

  1. preload the association
  2. start working with the associated struct that is preloaded, remove it from the embedded struct
  3. do your transformations on the associated struct. if you need the changeset validations use the changeset function from the association’s schema, not the embedded one
  4. insert the modified associated struct/changeset directly instead of being a part of the embedded struct
1 Like

If you’re happy for the data to be saved as json in the database, you can persist it like so:

Make the field a list of maps in the migration:

add :something, {:array, :map}

Use embeds_many in the schema:

embeds_many :something, MyEmbeddedSchema

Add a basic changeset to the embedded schema:

defmodule MyEmbeddedSchema do
  ...
  def changeset(schema, params) do
    schema
    |> cast(params, [:data])
  end
end

Instead of casting it with the rest of the fields use cast_embed:

params = %{name: "A", something: [%{data: :x}]}

schema
|> cast(params, [:name])
|> cast_embed(:something)