创建父

时间:2016-07-18 16:14:10

标签: elixir phoenix-framework ecto

我目前正在编写Phoenix编程中的代码,并且遇到了一个令我感到困惑的错误。

运行Rumbl.TestHelpers.insert_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_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

我真的很感激那些可以解释为什么我会收到这个错误的人。

2 个答案:

答案 0 :(得分:2)

修复它的事情是mix do deps.clean --all, deps.get, deps.compile && mix test

答案 1 :(得分:1)

问题在于您的变更集:

  

def changeset(model,params \\:invalid)do

您的默认值是:invalid原子。我也遵循编程凤凰,它说你可以传递:空或:无效原子。但:empty不再被接受。所以我也测试了:invalid

问题是,当您正在执行时不传递任何参数时,:invalid会使整个更改集无效,如您在错误消息中所示。

我的情况下的解决方案,我认为在您的情况下,正在将:invalid更改为%{},然后更改集参数将变为空地图,但仍然有效。它将适用于您的插入。