Phoenix表单中的ecto自定义类型?

时间:2019-03-14 01:30:58

标签: elixir phoenix-framework ecto

我在我的Phoenix应用程序的一种模式中使用Ecto自定义类型,如所述的here(具体来说,是利用Postgres Ranges指定range中的times,例如“在12:00-4:00之间”)。我可以毫无问题地从数据库中插入/检索数据库,但是我想出一个好方法来使用变更集和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仅用于关联。

1 个答案:

答案 0 :(得分:1)

这是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 %>

尽管我不知道在编辑保存的时间范围(分解time_select)时如何填充两个:allowed_hours。也许有人这样做。或者,您可以使用正确的名称和值呈现常规的html输入。

编辑3 ...还是行得通?

<%= time_select f, :allowed_hours_from, value: something(f.data.allowed_hours) %>