' changeset() '规范要求一个逻辑上不可为空的类型



我有以下代码:

defmodule Foo do
@moduledoc false
use Ecto.Schema
import Ecto.Changeset

@type t :: %__MODULE__{
id: integer(),
foo: String.t(),
baz_id: String.t(),
bar: String.t() | nil
}
embedded_schema do
field :foo, :string
field :bar, :string
end
@spec changeset(t() | Ecto.Changeset.t(), map()) :: Ecto.Changeset.t()
def changeset(bae \ %__MODULE__{}, attrs) do
bae
|> cast(attrs, @fields)
|> unique_constraint(:baz_id)
end
end
根据@type

的定义,foobaz_id不应该是nil。然而,dialyzer抱怨(与给定的@spec),因为默认值%__MODULE__{}将它们设置为nil

如果我将@type定义替换为:

...
@type t :: %__MODULE__{
id: integer() | nil,
foo: String.t() | nil,
baz_id: String.t() | nil,
bar: String.t() | nil
}
...

那么dialyzer将不会抱怨,但我不再捕获的想法,一些字段是不可空的。

changeset()按照目前的方式工作,并避免dialyzer抱怨这个特定的使用,这将是一个优雅的方法吗?

你显式地指定了违反透析器契约的默认参数(模式是一个没有默认值的裸结构体),这就是透析器抱怨的原因。

现在还不清楚,你应该如何处理一个空的%__MODULE__{},一旦它不被允许,但是回答这个问题,解决办法是接受nil参数作为默认值。

@spec changeset(
nil | t() | Ecto.Changeset.t(), map()
) :: Ecto.Changeset.t()
def changeset(bae \ nil, attrs) do
bae
|> Kernel.||(%__MODULE__{})
|> cast(attrs, @fields)
|> unique_constraint(:baz_id)
end

相关内容

  • 没有找到相关文章

最新更新