Ecto:变更集删除对父模型的更新

Ecto: changeset drops update to parent model

我正在尝试将更新保存到具有父级(状态)的记录(用户)。用户记录显示正常(显示,编辑)包括状态。用户记录可以根据自己的属性进行更新,但是用户选择的状态的任何更改都不会持久化。将用户状态从 1 更改为 2 时,从视图返回到控制器的用户参数看起来很好...从日志 ->

%{"email" => “e@e.com", "first_name" => “Abe",
"last_name" => “Sam", "password" => “foobar", "state_id" => "2"}

但是当它被传递给用户变更集时,它会返回对 state_id 的更改...从日志 ->

#Ecto.Changeset<action: nil,
changes: %{password: "foobar",
password_hash: “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx."},
errors: [], data: #SomeApp.User<>, valid?: true>

控制器中的更新是:

def update(conn, %{"id" => id, "user" => user_params}) do
  user = Repo.get!(User, id)
  changeset =  User.changeset(user, user_params)
  case Repo.update(changeset) do

相关的变更集代码是:

def changeset(model, params \ %{}) do
    model
    |> cast(params, [:email, :first_name, :last_name, :password])
    |> assoc_constraint(:state)
    |> validate_required([:email, :first_name, :last_name, :password])
    |> unique_constraint(:email)
    |> validate_length(:password, min: 4, max: 100)
    |> put_pass_hash()
  end

用户的架构是:

schema "users" do
    field :email, :string
    field :password,  :string, virtual: true
    field :password_hash, :string
    field :first_name, :string
    field :last_name, :string
    belongs_to :state, SomeApp.State

    timestamps()
  end

我这里做错了什么?我是否在我的变更集中遗漏了将参数中的 user_id 转换为变更集的内容?我希望我在做一些简单而愚蠢的事情 - 我真的花了几个小时试图阅读把它拆开,但我被卡住了!

由于您想使用 params 中的 state_id,您需要将 :state_id 添加到对 cast 的调用中的允许列表中。允许列表中没有 :state_id,该值将被忽略,这就是现在发生的情况。

|> cast(params, [:email, :first_name, :last_name, :password])

应该是

|> cast(params, [:email, :first_name, :last_name, :password, :state_id])