Elixir 创建父项时,上的Exto.InvalidChangesetError有许多关系

Elixir 创建父项时,上的Exto.InvalidChangesetError有许多关系,elixir,phoenix-framework,ecto,Elixir,Phoenix Framework,Ecto,我目前正在编写Phoenix的代码,遇到了一个让我困惑的错误 当我运行Rumbl.TestHelpers.insert\u user ** (Ecto.InvalidChangesetError) could not perform insert because changeset is invalid. * Changeset changes %{name: "Some user", password: "supersecret", password_hash: "$2b$12$ZaSx6

我目前正在编写Phoenix的代码,遇到了一个让我困惑的错误

当我运行
Rumbl.TestHelpers.insert\u user

** (Ecto.InvalidChangesetError) could not perform insert because changeset is invalid.

* Changeset changes

%{name: "Some user", password: "supersecret", password_hash: "$2b$12$ZaSx6WcTZnrRGrneHsrNF.oMx8if3yMNssnx1B/lGBD5/GPj17Ym6", username: "user50853EBB5B75FC40"}

* Changeset params

%{"name" => "Some user", "password" => "supersecret", "username" => "user50853EBB5B75FC40"}

* Changeset errors

[videos: "is invalid"]

(ecto) lib/ecto/repo/schema.ex:121: Ecto.Repo.Schema.insert!/4
Rumbl.TestHelpers.insert\u user
如下所示:

alias Rumbl.Repo

def insert_user(attrs \\ %{}) do
  changes = Dict.merge(%{
        name: "Some user",
        username: "user#{Base.encode16(:crypto.rand_bytes(8))}",
        password: "supersecret"
                   }, attrs)

  %Rumbl.User{}
  |> Rumbl.User.registration_changeset(changes)
  |> Repo.insert!()
end
Rumbl.User

defmodule Rumbl.User do
  use Rumbl.Web, :model

  schema "users" do
    field :name, :string
    field :username, :string
    field :password, :string, virtual: true
    field :password_hash, :string
    has_many :videos, Rumbl.Video

    timestamps
  end

  def changeset(model, params \\ :invalid) do
    model
    |> cast(params, ~w(name username), [])
    |> validate_length(:username, min: 1, max: 20)
    |> unique_constraint(:username)
  end

  def registration_changeset(model, params) do
    model
    |> changeset(params)
    |> cast(params, ~w(password), [])
    |> validate_length(:password, min: 6, max: 100)
    |> put_pass_hash()
  end

  defp put_pass_hash(changeset) do
    case changeset do
      %Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
        put_change(changeset, :password_hash, Comeonin.Bcrypt.hashpwsalt(pass))
      _ -> changeset
    end
  end
end
最后是
Rumbl.Video

defmodule Rumbl.Video do
  use Rumbl.Web, :model

  schema "videos" do
    field :url, :string
    field :title, :string
    field :description, :string
    belongs_to :user, Rumbl.User
    belongs_to :category, Rumbl.Category

    timestamps()
  end

  @doc """
  Builds a changeset based on the `struct` and `params`.
  """
  def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:url, :title, :description], [:category_id])
    |> validate_required([:url, :title, :description])
    |> assoc_constraint(:category)
  end
end

我非常感谢任何能够解释我为什么会出现此错误的人。

问题在于您的变更集中:

def变更集(模型,参数\\:无效)do

默认值是
:无效的
原子。我还遵循了编程Phoenix,它说您可以传递:empty或:invalid atom。但是
:空的
不再被接受。因此,我还测试了
:invalid

问题是,当您不传递任何参数时,正如您在错误消息中看到的那样:invalid使整个变更集无效


在我的例子中,我认为在你的例子中,解决方案是将
:invalid
更改为
%{}
,然后变更集参数将成为空映射,但仍然有效。它将在您的insert中工作。

修复这一切的方法是运行
mix do deps.clean--all,deps.get,deps.compile&&mix test

使用什么参数调用
insert\u user
?@Dogbert none,只是默认值。在某个地方,您正在传递一个:videos密钥,该密钥在创建用户时无效。你需要搜索它。另外,作为补充说明,Dict已经被弃用,取而代之的是Map。不幸的是,这是不正确的
TestHelpsers.insert_user
将更改作为参数发送到registration_变更集,然后将其传递到变更集。这意味着params将始终是一个包含以下数据的字典:
%{name:“Some user”,password:“supersecret”,username:“user”}
。如果我删除
has_many:videos
行,一切都可以正常工作。如果你为用户添加一个带有insert_视频的视频,它可以正常工作?我遇到了类似的问题,使用
%{}
而不是
:invalid
为我修复了它。谢谢您可以将“
”重置“:[“deps.clean--all”、“deps.get”、“deps.compile”]
作为
mix.exs中的
别名中的一个条目(如果它一直发生;)