I am trying to create an embedded schema that needs to save information about orders.
Sometimes orders have no customer_id and that is fine (for the application).
defmodule Order do
use Ecto.Schema
embedded_schema do
field(:customer_id, :integer | nil)
field(:stage, enum: [:bought | :in_shop_cart | :canceled])
field(:details, :string)
end
end
Problem
The issue here is that I get a compile error for customer_id:
(CompileError) misplaced operator |/2
The | operator is typically used between brackets as the cons operator:
[head | tail]
where head is a single element and the tail is the remaining of a list.
It is also used to update maps and structs, via the %{map | key: value} notation,
and in typespecs, such as @type and @spec, to express the union of two types
I understand the issue here is the use of :integer | nil. This is not a list, so the advice I get is not usable.
Question
How can I represent optional values in my embedded schema ? (specifically :something | nil)
So for my scenario, the field :details is nullable by default, correct?
A fixed version would therefore be:
defmodule Order do
use Ecto.Schema
embedded_schema do
field(:customer_id, :integer)
field(:stage, enum: [:bought | :in_shop_cart | :canceled])
field(:details, :string)
end
end
And then in the database columns, set null: false. I will also need to validate this requirement in changeset validations as @dimitarvp pointed out, correct?
defmodule Order do
use Ecto.Schema
embedded_schema do
field(:customer_id, :integer)
field(:stage, enum: [:bought | :in_shop_cart | :canceled])
field(:details, :string)
end
end
I made a mistake in my previous answer, you should add null: false to your migration, and in schema, you can just skip it.
I have a table called “action” and I am going to add a new column called “order” which will be the embedded schema I mention. I did not find anything that allows me to specify what fields can or cannot be null when defining the embedded schema or the migration.
Depending on the database you can use certain constraints for whatever column type is used to back :map. In postgres this would be json/jsonb column and you can e.g. use check constraints to enforce properties on them.
For a topic like this I’d strongly suggest looking at your used database docs just as much as at ecto.