Reputation: 17584
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
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.
How can I represent optional values in my embedded schema ? (specifically :something | nil
)
Upvotes: 0
Views: 1011
Reputation: 9578
The pipe operator |
is used to separate the head of a list from its tail (as the error mentions) and it gets used in @spec
definitions when defining allowed inputs/outputs.
Normally, the migrations are where the nullable/not-nullable definition really matters, but with a virtual schema, I think you're fine just specifying the data type (e.g. :integer
). If there's no value, a nil
will be used in its place (similar to how a struct's fields have nil
values unless defaults were defined). In other words
field(:customer_id, :integer)
# is the same as
field(:customer_id, :integer, default: nil)
If you wanted to indicate some "non-nullable" field in an Ecto schema, Set the :default
option appropriate, e.g.
field(:details, :string, default: "")
Upvotes: 2
Reputation: 41
First of all you can't use |
in schema like this.
As far as the first case is concerned like in customer_id
, you can use default
option to set default a default value if the value isn't provided.
In the second case of stage
You can use Ecto's Enum
to restrict only specific values to be entered in the db. You can do something like this:
field :status, Ecto.Enum, values: [:foo, :bar, :baz]
Here is some useful documentaion for further reading about Ecto Enum
Upvotes: 1