【问题标题】:Elixir Ecto: Casting multiple belongs_to relationship in a schema goes wrongElixir Ecto:在模式中强制转换多个 belongs_to 关系出错
【发布时间】:2021-09-11 09:11:03
【问题描述】:

首先:我有一个架构players和一个架构matches,我想在phoenix 1.6中建立它们之间的belong_to,has_many关系。我尝试过的:

defmodule TennisPhx.Matches.Match do
  use Ecto.Schema
  import Ecto.Changeset
  alias TennisPhx.Participants.Player

  schema "matches" do


    has_many :first_players, Player, foreign_key: :first_player_key_id   <------
    has_many :second_players, Player, foreign_key: :second_player_key_id  <-------

# other not relevant fields 


    timestamps()
  end

  @doc false
  def changeset(match, attrs) do
    match
    |> cast(attrs, [:tour_id, :first_player, :second_player, :starting_datetime, :location_id, :phase_id, :status_id, :player_unit_id])
    |> validate_required([:tour_id, :location_id, :phase_id, :player_unit_id])
  end
end
defmodule TennisPhx.Participants.Player do
  use Ecto.Schema
  import Ecto.Changeset

  alias TennisPhx.Events.Tour
  alias TennisPhx.Matches.Match

  schema "players" do
# other fields

    belongs_to :first_players, Match, foreign_key: :first_player_key_id
    belongs_to :second_players, Match, foreign_key: :second_player_key_id


    timestamps()

  end

  @doc false
  def changeset(player, attrs) do
    player
    |> cast(attrs, [:name, :nickname, :info, :birthdate])
    |> validate_required([:name])
  end
end

我在上下文中的“assign_match”函数:

  def assign_match(%Tour{} = tour, first_player, second_player, day, month, year, location, phase, unit) do
    tt = tour.id

    %Match{}
    |> Match.changeset(%{tour_id: tour.id, first_player: first_player, second_player: second_player, location_id: location, phase_id: phase, player_unit_id: unit})
    |> Repo.insert()

  end

还有迁移:

  def change do
    alter table("matches") do
      add(:first_player, references(:players, on_delete: :delete_all))
      add(:second_player, references(:players, on_delete: :delete_all))
    end
  end

我得到了什么错误:

unknown field `:first_player` given to cast. Either the field does not exist or it is a :through association (which are read-only). The known fields are: :first_players, :id, :inserted_at, :location, :location_id, :phase, :phase_id, :player_unit, :player_unit_id, :score, :second_players, :starting_datetime, :status, :status_id, :tour, :tour_id, :updated_at

为什么?我们可以清楚的看到迁移中的字段是first_player,单数。当将列重命名为复数时,first_playerssecond_players 我明白了:

[error] GenServer #PID<0.609.0> terminating
** (RuntimeError) casting assocs with cast/4 for :first_players field is not supported, use cast_assoc/3 instead

我在这里做错了什么?想不通。。

我已关注this 的关系和multiple_belongs_to thisthis 的文章

【问题讨论】:

    标签: elixir ecto has-and-belongs-to-many phoenix


    【解决方案1】:

    在迁移中,first_player 是单数。在 Match 模式中,first_players 是复数。这些不匹配。

    如第二条错误消息中所述,您需要在 Match.changeset 函数中使用 cast_assoc/3 而不是 cast/4。请参阅此处的文档以了解示例用法:https://hexdocs.pm/ecto/Ecto.Changeset.html#cast_assoc/3

    【讨论】:

    • 谢谢你,但是我应该如何处理具有 2 个 has_many 关系的 cast_assoc?
    • 你可以把它们放在一起。所以你的变更集函数看起来像这样:pastebin.com/bCvvg1KE
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 2016-01-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多