Phoenix Form 中的 Ecto 自定义类型?
Ecto custom type in Phoenix Form?
我在 Phoenix 应用程序的一个模式中使用 Ecto 自定义类型,如 here (specifically, making use of Postgres Ranges to specify a range of times 所述,如 "between 12:00-4:00")。我能够 insert/retrieve 毫无问题地从数据库中获取数据,但我无法想出一种使用变更集和 Phoenix 表单为用户呈现表单的好方法。
所以架构看起来像这样(TimeRange
是自定义类型):
@primary_key false
@foreign_key_type :binary_id
schema "person_messaging_settings" do
field :can_receive_email, :boolean, null: false
field :can_receive_sms, :boolean, null: false
field :allowed_hours, MyApp.Ecto.TimeRange
belongs_to :person, Person
timestamps()
end
我可以使用 inputs_for
作为 belongs_to
关联,理想情况下我可以在我的 EEX 模板中做这样的事情:
<%= form_for @changeset, Routes.settings_path(@conn, :update), fn f -> %>
<!-- other field values -->
<%= inputs_for f, :allowed_hours, fn ah -> %>
<%= time_select ah, :upper %>
<%= time_select ah, :lower %>
<% end %>
<% end %>
但这会引起抱怨,因为 inputs_for
严格用于关联。
这是一个未经测试的原始想法 virtual fields。
架构文件:
schema "person_messaging_settings" do
# ...
field :allowed_hours_from, :time, virtual: true
field :allowed_hours_to, :time, virtual: true
end
def changeset do
record
|> cast(attrs, [..., :allowed_hours_from, :allowed_hours_to])
|> set_allowed_hours()
|> validate_required([..., :allowed_hours])
end
defp set_allowed_hours(changeset) do
case {get_field(changeset, :allowed_hours_from), get_field(changeset, :allowed_hours_to)} do
{nil, nil} -> changeset
{nil, _} -> changeset
{_, nil} -> changeset
{from, to} -> put_change(changeset, :allowed_hours, "#{from}-#{to}")
end
end
和表格:
<%= form_for @changeset, Routes.settings_path(@conn, :update), fn f -> %>
<!-- other field values -->
<%= time_select f, :allowed_hours_from %>
<%= time_select f, :allowed_hours_to %>
<% end %>
尽管我不知道在编辑保存的时间范围(分解 :allowed_hours
)时如何填充两个 time_select
。也许其他人会这样做。或者您使用正确的名称和值呈现常规 html 输入。
编辑 3... 或者这行得通吗?
<%= time_select f, :allowed_hours_from, value: something(f.data.allowed_hours) %>
我在 Phoenix 应用程序的一个模式中使用 Ecto 自定义类型,如 here (specifically, making use of Postgres Ranges to specify a range of times 所述,如 "between 12:00-4:00")。我能够 insert/retrieve 毫无问题地从数据库中获取数据,但我无法想出一种使用变更集和 Phoenix 表单为用户呈现表单的好方法。
所以架构看起来像这样(TimeRange
是自定义类型):
@primary_key false
@foreign_key_type :binary_id
schema "person_messaging_settings" do
field :can_receive_email, :boolean, null: false
field :can_receive_sms, :boolean, null: false
field :allowed_hours, MyApp.Ecto.TimeRange
belongs_to :person, Person
timestamps()
end
我可以使用 inputs_for
作为 belongs_to
关联,理想情况下我可以在我的 EEX 模板中做这样的事情:
<%= form_for @changeset, Routes.settings_path(@conn, :update), fn f -> %>
<!-- other field values -->
<%= inputs_for f, :allowed_hours, fn ah -> %>
<%= time_select ah, :upper %>
<%= time_select ah, :lower %>
<% end %>
<% end %>
但这会引起抱怨,因为 inputs_for
严格用于关联。
这是一个未经测试的原始想法 virtual fields。
架构文件:
schema "person_messaging_settings" do
# ...
field :allowed_hours_from, :time, virtual: true
field :allowed_hours_to, :time, virtual: true
end
def changeset do
record
|> cast(attrs, [..., :allowed_hours_from, :allowed_hours_to])
|> set_allowed_hours()
|> validate_required([..., :allowed_hours])
end
defp set_allowed_hours(changeset) do
case {get_field(changeset, :allowed_hours_from), get_field(changeset, :allowed_hours_to)} do
{nil, nil} -> changeset
{nil, _} -> changeset
{_, nil} -> changeset
{from, to} -> put_change(changeset, :allowed_hours, "#{from}-#{to}")
end
end
和表格:
<%= form_for @changeset, Routes.settings_path(@conn, :update), fn f -> %>
<!-- other field values -->
<%= time_select f, :allowed_hours_from %>
<%= time_select f, :allowed_hours_to %>
<% end %>
尽管我不知道在编辑保存的时间范围(分解 :allowed_hours
)时如何填充两个 time_select
。也许其他人会这样做。或者您使用正确的名称和值呈现常规 html 输入。
编辑 3... 或者这行得通吗?
<%= time_select f, :allowed_hours_from, value: something(f.data.allowed_hours) %>