首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有tsrange字段的Ecto架构

带有tsrange字段的Ecto架构
EN

Stack Overflow用户
提问于 2017-08-13 05:58:51
回答 2查看 322关注 0票数 1

我有一个带有tsrange column的Postgres表,我想把它包含在我的Ecto模块的schema中。我看到那个Postgrex.Range exists了。我试过了:

代码语言:javascript
复制
schema "clients" do
  field :valid_at, Postgrex.Range
  ...
end

但这给了我这个错误:

代码语言:javascript
复制
** (ArgumentError) invalid or unknown type Postgrex.Range for field :valid_at
    lib/ecto/schema.ex:1785: Ecto.Schema.check_type!/3
    lib/ecto/schema.ex:1473: Ecto.Schema.__field__/4

有什么建议吗?我使用Phoenix 1.3和Ecto master分支。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-05 03:07:14

看起来@TheAnh的方法是正确的,但这是真正对我有效的方法:

代码语言:javascript
复制
defmodule Myapp.TsRange do
  @behaviour Ecto.Type

  def type, do: :tsrange

  def cast(nil),            do: {:ok, nil}
  def cast([lower, upper]), do: {:ok, [lower, upper]}
  def cast(_),              do: :error

  def load(%Postgrex.Range{lower: lower, upper: upper}) do
    lower = lower |> to_datetime
    upper = upper |> to_datetime
    case [lower, upper] do
      [nil, nil]                   -> {:ok, [nil, nil]}
      [{:ok, lower}, {:ok, upper}] -> {:ok, [lower, upper]}
      _ -> :error
    end
  end
  def load(_), do: :error

  def dump([lower, upper]) do
    {:ok, %Postgrex.Range{lower: lower |> from_datetime,
                          upper: upper |> from_datetime,
                          upper_inclusive: false}}
  end
  def dump(_), do: :error

  defp to_datetime(nil), do: nil
  defp to_datetime({{y, m, d}, {h, min, s, ms}}) do
    NaiveDateTime.new(y, m, d, h, min, s, ms)
  end

  defp from_datetime(nil), do: nil
  defp from_datetime(dt) do
    {{dt.year, dt.month, dt.day}, {dt.hour, dt.minute, dt.second, elem(dt.microsecond, 0)}}
  end

end
票数 0
EN

Stack Overflow用户

发布于 2017-08-13 11:19:29

我认为你应该为tsrange创建一个自定义类型来使用Ecto。

代码语言:javascript
复制
defmodule YourApp.TimestampRange do
 @behaviour Ecto.Type

  def type, do: :tsrange

  def cast([lower, upper]) do
    {:ok, [lower, upper]}
  end

  def cast(_), do: :error 

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

  def dump([lower, upper]) do
    {:ok, %Postgrex.Range{lower: lower, upper: upper, upper_inclusive: false}}
  end

  def dump(_), do: :error
end

关于包含性边界检出PostgreSQL documentation

然后在你的应用中,你可以使用:

代码语言:javascript
复制
schema "clients" do
  field :valid_at, YourApp.TimestampRange
  ...
end
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45655274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档