为什么当我有主键并且有值时,为什么会增加Ecto.NoPrimaryKeyValueError?

问题描述 投票:0回答:1

每当我运行此代码:

{:ok, act_1} = %Kempelen.Models.GameAct{}
  |> Kempelen.Models.GameAct.changeset(%{
      game_play: place_road,
      game_player: player_1,
      game_round: round_1
    })
  |> Kempelen.Database.Repo.insert

我遇到此异常:

** (Ecto.NoPrimaryKeyValueError) struct `%Kempelen.Models.GamePlayer{__meta__: #Ecto.Schema.Metadata<:loaded, "game_players">, account: %Kempelen.Models.Account{__meta__: #Ecto.Schema.Metadata<:loaded, "accounts">, email: "[email protected]", game_players: #Ecto.Association.NotLoaded<association :game_players is not loaded>, game_rounds: #Ecto.Association.NotLoaded<association :game_rounds is not loaded>, game_tables: #Ecto.Association.NotLoaded<association :game_tables is not loaded>, id: "65880220-e39b-450d-ba7f-0642bea8dbc8", inserted_at: ~N[2020-02-16 16:15:33], name: nil, onboarding_state: "converted", organization_memberships: #Ecto.Association.NotLoaded<association :organization_memberships is not loaded>, organizations: #Ecto.Association.NotLoaded<association :organizations is not loaded>, password: nil, password_hash: nil, role_state: "user", unconfirmed_email: "[email protected]", updated_at: ~N[2020-02-16 16:15:33], username: nil}, account_id: "65880220-e39b-450d-ba7f-0642bea8dbc8", game_acts: #Ecto.Association.NotLoaded<association :game_acts is not loaded>, game_robot: nil, game_robot_id: nil, game_table: %Kempelen.Models.GameTable{__meta__: #Ecto.Schema.Metadata<:loaded, "game_tables">, game: %Kempelen.Models.Game{__meta__: #Ecto.Schema.Metadata<:loaded, "games">, game_plays: #Ecto.Association.NotLoaded<association :game_plays is not loaded>, game_tables: #Ecto.Association.NotLoaded<association :game_tables is not loaded>, id: "31eee3b8-b43c-411a-8528-479269c63d2d", inserted_at: ~N[2020-02-16 16:15:33], name: "Settlers of Catan", organization: %Kempelen.Models.Organization{__meta__: #Ecto.Schema.Metadata<:loaded, "organizations">, accounts: #Ecto.Association.NotLoaded<association :accounts is not loaded>, games: #Ecto.Association.NotLoaded<association :games is not loaded>, id: "3311c337-f480-4292-9582-c45f249730b2", inserted_at: ~N[2020-02-16 16:15:32], name: "Hasbro", organization_memberships: #Ecto.Association.NotLoaded<association :organization_memberships is not loaded>, robots: #Ecto.Association.NotLoaded<association :robots is not loaded>, slug: "hasbro", updated_at: ~N[2020-02-16 16:15:32]}, organization_id: "3311c337-f480-4292-9582-c45f249730b2", slug: "settlers-of-catan", updated_at: ~N[2020-02-16 16:15:33]}, game_id: "31eee3b8-b43c-411a-8528-479269c63d2d", game_players: #Ecto.Association.NotLoaded<association :game_players is not loaded>, game_rounds: #Ecto.Association.NotLoaded<association :game_rounds is not loaded>, id: "2cda5e3c-c57d-4117-a541-0c6a409984b6", inserted_at: ~N[2020-02-16 16:15:33], name: "FFA", slug: "ffa", updated_at: ~N[2020-02-16 16:15:33]}, game_table_id: "2cda5e3c-c57d-4117-a541-0c6a409984b6", host: true, id: "591227e6-3ea0-4f3f-8a44-471d7073c2df", inserted_at: ~N[2020-02-16 16:15:33], name: "Kurtis", slug: "kurtis", updated_at: ~N[2020-02-16 16:15:33]}` is missing primary key value

这里是模特:

defmodule Kempelen.Models.GameAct do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "game_acts" do
    belongs_to :game_play, Kempelen.Models.GamePlay, primary_key: true
    belongs_to :game_player, Kempelen.Models.GamePlayer, primary_key: true
    belongs_to :game_round, Kempelen.Models.GameRound, primary_key: true

    timestamps()
  end

  @doc false
  def changeset(%{} = record, attributes \\ %{}) do
    record
    |> cast(attributes, [])
    |> validate_required([])
    |> assoc_constraint(:game_play)
    |> assoc_constraint(:game_player)
    |> assoc_constraint(:game_round)
    |> put_assoc(:game_play, attributes.game_play)
    |> put_assoc(:game_player, attributes.game_player)
    |> put_assoc(:game_round, attributes.game_round)
  end
end
defmodule Kempelen.Models.GamePlayer do
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key {:id, :binary_id, autogenerate: true}
  @foreign_key_type :binary_id
  schema "game_players" do
    field :name, :string
    field :slug, Kempelen.Slugs.Name.Type
    field :host, :boolean, default: false
    belongs_to :game_table, Kempelen.Models.GameTable, primary_key: true
    belongs_to :account, Kempelen.Models.Account, primary_key: true
    belongs_to :game_robot, Kempelen.Models.GameRobot, primary_key: true
    has_many :game_acts, Kempelen.Models.GameAct

    timestamps()
  end

  @doc false
  def changeset(%{} = record, attributes \\ %{}) do
    record
      |> cast(attributes, [:name, :host])
      |> validate_required([:name, :host])
      |> assoc_constraint(:game_table)
      |> assoc_constraint(:account)
      |> assoc_constraint(:game_robot)
      |> Kempelen.Slugs.Name.maybe_generate_slug
      |> Kempelen.Slugs.Name.unique_constraint
      |> put_assoc(:game_robot, attributes[:game_robot])
      |> put_assoc(:account, attributes[:account])
      |> put_assoc(:game_table, attributes.game_table)
  end
end

不仅是game_play模型,也发生在game_player中。

变更集似乎也认为它是有效的:

#Ecto.Changeset<
  action: nil,
  changes: %{
    game_play: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
     data: #Kempelen.Models.GamePlay<>, valid?: true>,
    game_player: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
     data: #Kempelen.Models.GamePlayer<>, valid?: true>,
    game_round: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
     data: #Kempelen.Models.GameRound<>, valid?: true>
  },
  errors: [],
  data: #Kempelen.Models.GameAct<>,
  valid?: true
>
ecto
1个回答
0
投票

好,所以我终于明白了。事实证明,虽然我希望accountgame_robot关系是可选的(在业务逻辑中一个或另一个),但是架构中primary_key: truebelongs_to选项意味着外键列必须具有一个值。

© www.soinside.com 2019 - 2024. All rights reserved.