【问题标题】:Ecto: changeset drops update to parent modelEcto:变更集删除对父模型的更新
【发布时间】:2017-08-02 19:15:35
【问题描述】:

我正在尝试将更新保存到具有父级(状态)的记录(用户)。用户记录显示正常(在显示、编辑中),包括状态。用户记录可以根据自己的属性进行正常更新,但不会保留对用户选择的状态的任何更改。将用户状态从 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 转换为变更集的内容?我希望我在做一些简单而愚蠢的事情——我真的花了好几个小时试图把这个分开,但我被困住了!

【问题讨论】:

    标签: phoenix-framework ecto


    【解决方案1】:

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

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

    应该是

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

    【讨论】:

    • 谢谢 - 我已经尝试过了,phoenix 抛出一个错误,说你需要使用 cast_assoc 来投射关联。我会重现并得到给出的确切错误。但随后尝试抛出一个单独的错误,抱怨 cast_assoc 是针对儿童的。
    • 我错了,它现在完全有效,就像你说的那样。不知道为什么它以前不起作用(也许我没有 assoc_constraint 在那里)。非常感谢 - 你让我很开心!
    • 我想通了:我想我之前在演员表中添加了 :state 而不是 :state_id。我发现属于的命名与实际的列约定(state vs state_id)并没有立即直观。不过,我认为我在做正确的事?
    • 是的,state_id 在这里是正确的。 state_id 将始终包含一个整数。 state 将是关联的 State 模型实例,并且仅在您预加载关联时才会填充。每当您修改该整数值时,您都需要使用state_id。如果您有一个表单来创建用户并为该用户创建一个新状态,您将使用cast_assoc + :state
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多