道歉,如果這聽起來像一個愚蠢的問題,但我被難以置信的Ecto拋出的錯誤。Ecto一對一多態關聯
我想實現一對一的多態關聯。我已閱讀關於在Ecto中實現多態關聯的文檔,但我的要求需要一對一的關係。
guard -> guard_user -> user
operator -> operator_user -> user
其中
guard
-----
id
position
guard_user
----
guard_id
user_id
user
-----
id
email
password
name
也是如此operator
和operator_user
表。
defmodule Example.Guards.Guard do
use Ecto.Schema
import Ecto.Changeset
alias Example.Guards.Guard
alias Example.Guards.GuardUser
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "guards" do
field :position, :string
has_one :guard_user, GuardUser
has_one :user, through: [:guard_user, :user]
timestamps()
end
@doc false
def changeset(%Guard{} = guard, attrs \\ %{}) do
guard
|> cast(attrs, [:position])
|> cast_assoc(:guard_user, required: true)
end
end
defmodule Example.Guards.GuardUser do
use Ecto.Schema
import Ecto.Changeset
alias Example.Guards.Guard
alias Example.Accounts.User
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "guard_user" do
belongs_to :guard, Guard
belongs_to :user, User
timestamps()
end
@doc false
def changeset(guard_user, attrs \\ %{}) do
guard_user
|> cast_assoc(:user, required: true)
end
end
defmodule Example.Accounts.User do
use Ecto.Schema
import Ecto.Changeset
alias Example.Accounts.User
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "users" do
field :email, :string
field :password, :string
timestamps()
end
@doc false
def changeset(%User{} = user, attrs) do
user
|> cast(attrs, [:email, :password])
|> validate_required([:email, :password])
|> unique_constraint(:email)
end
end
當我運行我的測試
,
test "create guard" do
params = %{
"position" => "Guard",
"guard_user" => %{
"user" => %{
"email" => "[email protected]",
"password" => "example"
}
}
}
changeset = Guard.changeset(%Guard{}, params)
assert changeset.valid?
end
以下錯誤拋出:
** (FunctionClauseError) no function clause matching in Ecto.Changeset.cast_relation/4
The following arguments were given to Ecto.Changeset.cast_relation/4:
# 1
:assoc
# 2
%Example.Guards.GuardUser{__meta__: #Ecto.Schema.Metadata<:built, "guard_user">, guard: #Ecto.Association.NotLoaded<association :guard is not loaded>, guard_id: nil, id: nil, inserted_at: nil, updated_at: nil, user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: nil}
# 3
:user
# 4
[required: true]
Attempted function clauses (showing 2 out of 2):
defp cast_relation(type, %Ecto.Changeset{data: data, types: types}, _name, _opts) when data == nil or types == nil
defp cast_relation(type, %Ecto.Changeset{} = changeset, key, opts)
code: changeset = Guard.changeset(%Guard{}, params)
stacktrace:
(ecto) lib/ecto/changeset.ex:665: Ecto.Changeset.cast_relation/4
(ecto) lib/ecto/changeset.ex:712: anonymous fn/4 in Ecto.Changeset.on_cast_default/2
(ecto) lib/ecto/changeset/relation.ex:100: Ecto.Changeset.Relation.do_cast/5
(ecto) lib/ecto/changeset/relation.ex:237: Ecto.Changeset.Relation.single_change/5
(ecto) lib/ecto/changeset.ex:691: Ecto.Changeset.cast_relation/4
test/example/guards/guard_test.exs:29: (test)
你可以發佈錯誤的整個堆棧跟蹤? – Dogbert
@Dogbert我已經編輯帖子以包括堆棧跟蹤 –