变更集更改中不包含ecto模式默认值

时间:2018-10-13 13:03:10

标签: elixir ecto

请考虑以下架构:

defmodule EctoBug.Post do
  use Ecto.Schema
  import Ecto.Changeset

  schema "posts" do
    field :title, :string, default: "test"

    timestamps()
  end

  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title])
    |> validate_required([:title])
  end
end

如果我愿意

changeset = EctoBug.Post.changeset(%EctoBug.Post{}, %{title: "test"})

title字段在changes中不存在:

#Ecto.Changeset<action: nil, changes: %{}, errors: [], data: #EctoBug.Post<>, valid?: true>

关于此行为,我找不到任何内容。

这是一个错误吗?

1 个答案:

答案 0 :(得分:4)

Ecto的变更集结构包含应用于模式/结构的变更。默认值未显示为更改的原因是,当您执行%EctoBug.Post{}时,它将填充您在架构上设置的默认值。然后,当您转换参数时,由于字段的原始值和转换值是相同的,因此这并不是真正的更改,也没有这样标记。

如果愿意

changeset = EctoBug.Post.changeset(%EctoBug.Post{}, %{title: "test"})
Ecto.Changeset.get_field(changeset, :title)

您应该看到已设置标题。尽管Ecto.Changeset.get_change(changeset, :title)会给您零,因为它与最初给出的原始结构相比没有变化。

如果您为字段title提供的值与默认值不同,则应该看到将其作为更改进行跟踪。

因为它是这样工作的,所以现在,如果您有一个尝试更新而不是创建的记录,并且对它进行了一些与已存在的参数相同的参数转换,那么ecto可以跳过尝试更新该参数的操作。记录,因为它可以看到没有任何变化。对于插入,即使没有更改,Ecto也会尝试插入。