This is specifically me creating a custom date from from elements. I have a form that collects the day and month of birth of a person (I'm not interested in the year). So I use the following, to create the form entry for the day_and_month_of_birth element this post is about:
<div class="form-group">
<div class="row">
<div class="col-md-5">Day / Month of Birth</div>
<%= date_select f, :day_and_month_of_birth, builder: fn b -> %>
<div class="col-md-3">
<%= b.(:day, []) %>
</div>
/
<div class="col-md-4">
<%= b.(:month, []) %>
</div>
<% end %>
<%= error_tag f, :day_and_month_of_birth %>
</div>
</div>
In my model I have:
defmodule RocfDev.Registration do
use RocfDev.Web, :model
schema "registration" do
field :title, :string, virtual: true
field :firstname, :string, virtual: true
field :surname, :string, virtual: true
field :day_and_month_of_birth, Ecto.Date, virtual: true
end
def changeset(model, params \\ %{}) do
model
|> cast(params, [
:title,
:firstname,
:surname,
:day_and_month_of_birth
])
end
Currently when I post the form, I get the error unrecognized date %{"day" => "1", "month" => "1"}.
I suppose it's because there's no day and month field in the registration schema. My questions are:
1st, Since I'm not interested in the year of birth, is Ecto.Date still the appropriate type to use for the day_and_month_of_birth field?
2nd, How do I resolve the error?
Basically, you have two integer ranges
1..12and1..31. But there are tons of limitations/constraints on their pair:2and30is invalid, etc. That’s whyEcto.Datetype is still looking applicable here. To use it, one might force the year to always be, say,2000, and pass this value back and forth to your frontend, using the hidden field to “display” it and pass back. That way you could not care aboutunrecognized dateerrors: from now on you’ll get%{"year" => 2000, "day" => "1", "month" => "1"}here.On the other hand, just day and month value is an incomplete information to verify the date, due to leap years existence. You can’t prove whether
February, 29is a valid date of birth or not, without knowing the year.2016/2/29is valid, while2017/2/29is not. From this point of view, it sounds reasonable to quit abusingEcto.Dateand use just two range fields, both of type integer.