使用自定义DateRange Ecto类型转换错误

时间:2017-11-11 21:43:35

标签: date elixir ecto postgrex

我正在编写一个我正在编写的自定义Ecto类型的问题。它由%Postgrex.Range{}类型支持。 代码是

defmodule Foo.Ecto.DateRange do

  @behaviour Ecto.Type

  def type, do: :daterange

  def cast(%{"lower" => lower, "upper" => upper}) do
    new_lower = Date.from_iso8601! lower
    new_upper = Date.from_iso8601! upper
    {:ok, Date.range(new_lower, new_upper)}
  end

  def cast(%Date.Range{}=range) do
    {:ok, range}
  end

  def cast(_), do: :error

  def load(%Postgrex.Range{lower: lower, upper: upper}) do
    {:ok, Date.range(lower, upper)}
  end

  def load(_), do: :error

  def dump(%Date.Range{}=range) do
    {:ok, %Postgrex.Range{lower: range.first, upper: range.last}}
  end

  def dump(_), do: :error
end

迁移

  def change do
    create table(:users) do
      add :email,             :string, null: false
      add :username,          :string
      add :name,              :string, null: false
      add :password_hash,     :text,   null: false
      add :period,            :daterange
      timestamps()
    end

用户架构

schema "users" do
  field :username,         :string
  field :name,             :string
  field :email,            :string
  field :password_hash,    :string
  field :password,         :string, virtual: true
  field :period,           Foo.Ecto.DateRange

seeds.exs中有问题的代码就是这个:

today    = Date.utc_today()

{:ok, user2} = create_user %{name: "Gloubi Boulga",
  email: "gloub@boul.ga", password: "xptdr32POD?é23PRK*efz",
  period: Date.range(today, Timex.shift(today, months: 2))
}

最后,错误就是这个:

* (CaseClauseError) no case clause matching: {~D[2017-11-04]}
    (ecto) lib/ecto/adapters/postgres/datetime.ex:40: Ecto.Adapters.Postgres.TypeModule.encode_value/2
    (ecto) /home/tchoutri/dev/Projects/Foo/deps/postgrex/lib/postgrex/type_module.ex:717: Ecto.Adapters.Postgres.TypeModule.encode_params/3
[…]
priv/repo/seeds.exs:33: anonymous fn/0 in :elixir_compiler_1.__FILE__/1

当然,我不明白为什么这种转换正在发生,这非常令人沮丧,特别是考虑到创建由%Postgrex.Range{}支持的自定义Ecto类型应该有点微不足道的。

编辑:我在演员表中添加了一些Logger.debug,我可以看到

[debug] Casting new_date #DateRange<~D[2017-11-11], ~D[2018-01-11]> 

出现和

%Postgrex.Range{lower: ~D[2017-11-11], lower_inclusive: true, upper: ~D[2018-01-11], upper_inclusive: true}

dump函数中。

3 个答案:

答案 0 :(得分:0)

%Postgrex.Range{}内,当前版本的Postgrex(0.13.3)需要%Postgrex.Date{}秒。请参阅相关测试here

但是,如链接中所示,%Postgrex.Date{}在下一版本中已弃用,您应该从0.14开始使用%Date{}(仍在开发中)。

答案 1 :(得分:0)

我今天遇到过这个。我希望这仍然有帮助:

def dump(%Date.Range{} = range) do
  {:ok, %Postgrex.Range{lower: Date.to_erl(range.first), upper: Date.to_erl(range.last)}}
end

答案 2 :(得分:0)

这是我最终的结果:

ul.ul li {
  list-style: none;
  width: 100%;
  height: 19px;
  background: #d3c3e2;
  border: 1px solid red;
  box-sizing: border-box;
}

ul.ul li .span-1 {
  position: relative;
  width: 102px;
  border-right: 1px solid black;
  margin-right: 20px;
  padding-right: 12px;
}

ul.ul li .span-2 {
  position: relative;
  width: 50%;
  border-right: 1px solid black;
}