Ecto 变更集中的转换错误
Casting error in Ecto changesets
我有以下模型(用于聊天室),但在使用变更集时遇到问题:
defmodule Elemental.TxChat.Room do
use Elemental.TxChat.Web, :model
schema "rooms" do
field :name, :string
# Foreign key indicating which user created this room
# One user can create any number of rooms
belongs_to :created_by, Elemental.TxChat.User
field :created_from_app, :integer
many_to_many :members, Elemental.TxChat.User, join_through: "rooms_users"
timestamps()
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :created_by, :created_from_app])
|> validate_required([:name, :created_by, :created_from_app])
end
end
然后我想,我会尝试将一个空结构传递给变更集并查看它产生的错误。所以我做了(在别名之后):
iex(4)> c = Room.changeset(%Room{}, %{})
** (RuntimeError) casting assocs with cast/3 is not supported, use cast_assoc/3 instead
(ecto) lib/ecto/changeset.ex:440: Ecto.Changeset.type!/2
(ecto) lib/ecto/changeset.ex:415: Ecto.Changeset.process_param/8
(elixir) lib/enum.ex:1151: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(elixir) lib/enum.ex:1151: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(ecto) lib/ecto/changeset.ex:391: Ecto.Changeset.do_cast/7
(tx_chat) web/models/room.ex:19: Elemental.TxChat.Room.changeset/2
然后我认为具有belongs_to
等的模型可以与cast_assoc
一起使用,所以我更改了函数名称。现在:
iex(4)> c = Room.changeset(%Room{}, %{})
** (FunctionClauseError) no function clause matching in Ecto.Changeset.cast_assoc/3
(ecto) lib/ecto/changeset.ex:518: Ecto.Changeset.cast_assoc(%Elemental.TxChat.Room{__meta__: #Ecto.Schema.Metadata<:built, "rooms">, created_by: #Ecto.Association.NotLoaded<association :created_by is not loaded>, created_by_id: nil, created_from_app: nil, id: nil, inserted_at: nil, members: #Ecto.Association.NotLoaded<association :members is not loaded>, name: nil, updated_at: nil}, %{}, [:name, :created_by, :created_from_app])
(tx_chat) web/models/room.ex:19: Elemental.TxChat.Room.changeset/2
我做错了什么?
如评论中所述,您想将现有用户与新房间相关联。您可以通过在传递给 cast
的字段列表中添加 created_by_id
和 assoc_constraint(:created_by)
,然后将密钥 created_by_id
中的用户 ID 发送到 Room.changeset/2
来完成此操作.这应该有效:
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :created_by_id, :created_from_app])
|> validate_required([:name, :created_by_id, :created_from_app])
|> assoc_constraint(:created_by)
end
然后创建房间:
Room.changeset(%Room{}, %{name: "foo", created_by_id: 1, created_from_app: 1})
|> Repo.insert
我有以下模型(用于聊天室),但在使用变更集时遇到问题:
defmodule Elemental.TxChat.Room do
use Elemental.TxChat.Web, :model
schema "rooms" do
field :name, :string
# Foreign key indicating which user created this room
# One user can create any number of rooms
belongs_to :created_by, Elemental.TxChat.User
field :created_from_app, :integer
many_to_many :members, Elemental.TxChat.User, join_through: "rooms_users"
timestamps()
end
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :created_by, :created_from_app])
|> validate_required([:name, :created_by, :created_from_app])
end
end
然后我想,我会尝试将一个空结构传递给变更集并查看它产生的错误。所以我做了(在别名之后):
iex(4)> c = Room.changeset(%Room{}, %{})
** (RuntimeError) casting assocs with cast/3 is not supported, use cast_assoc/3 instead
(ecto) lib/ecto/changeset.ex:440: Ecto.Changeset.type!/2
(ecto) lib/ecto/changeset.ex:415: Ecto.Changeset.process_param/8
(elixir) lib/enum.ex:1151: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(elixir) lib/enum.ex:1151: Enum."-map_reduce/3-lists^mapfoldl/2-0-"/3
(ecto) lib/ecto/changeset.ex:391: Ecto.Changeset.do_cast/7
(tx_chat) web/models/room.ex:19: Elemental.TxChat.Room.changeset/2
然后我认为具有belongs_to
等的模型可以与cast_assoc
一起使用,所以我更改了函数名称。现在:
iex(4)> c = Room.changeset(%Room{}, %{})
** (FunctionClauseError) no function clause matching in Ecto.Changeset.cast_assoc/3
(ecto) lib/ecto/changeset.ex:518: Ecto.Changeset.cast_assoc(%Elemental.TxChat.Room{__meta__: #Ecto.Schema.Metadata<:built, "rooms">, created_by: #Ecto.Association.NotLoaded<association :created_by is not loaded>, created_by_id: nil, created_from_app: nil, id: nil, inserted_at: nil, members: #Ecto.Association.NotLoaded<association :members is not loaded>, name: nil, updated_at: nil}, %{}, [:name, :created_by, :created_from_app])
(tx_chat) web/models/room.ex:19: Elemental.TxChat.Room.changeset/2
我做错了什么?
如评论中所述,您想将现有用户与新房间相关联。您可以通过在传递给 cast
的字段列表中添加 created_by_id
和 assoc_constraint(:created_by)
,然后将密钥 created_by_id
中的用户 ID 发送到 Room.changeset/2
来完成此操作.这应该有效:
def changeset(struct, params \ %{}) do
struct
|> cast(params, [:name, :created_by_id, :created_from_app])
|> validate_required([:name, :created_by_id, :created_from_app])
|> assoc_constraint(:created_by)
end
然后创建房间:
Room.changeset(%Room{}, %{name: "foo", created_by_id: 1, created_from_app: 1})
|> Repo.insert