在长生不老药中,应该如何使用put_assoc?

In elixir, how put_assoc is supposed to be used?

提问人:Lucas 提问时间:10/30/2023 最后编辑:Lucas 更新时间:10/31/2023 访问量:50

问:

对于一个项目,我需要在凤凰城的 Elxir 创建一个小应用,使用 Ecto 作为 ORM。

我是这项技术的完全初学者,我在多对多关联上遇到了一个保存问题。

这是关于团队<>用户关系,其中用户可以拥有多个团队,团队可以包含多个用户。目前,db 和 objects 似乎不错。

这是我的模式:

Teams 架构

 schema "teams" do
    field :description, :string
    field :title, :string
    field :date_creation, :naive_datetime
    belongs_to :manager, BackEndService.Users.User
    many_to_many :users, BackEndService.Users.User, join_through: "users_teams"

    timestamps(type: :utc_datetime)
  end

用户架构

  schema "users" do
    field :username, :string
    field :email, :string
    field :hash_password, :string
    field :grade, :integer
    has_many :clocks, BackEndService.Clocks.Clock
    many_to_many :teams, BackEndService.Teams.Team, join_through: "users_teams"

    timestamps(type: :utc_datetime)
  end

真正的问题是当我尝试将用户添加到如下所示的团队时:

  1. 首先,我从列表中获取用户:

    def get_users(ids) do
      users_from_list_query =
      from u in User,
      where: u.id in ^ids
    
      Repo.all(users_from_list_query)
      |> Repo.preload([:teams])
    end
    
  2. 然后我尝试将它们插入到一个团队中:

    users_to_inject = Users.get_users(attrs.users_ids)
    
    team = get_team!(attrs.team_id)
    
    team
    |> Repo.preload([:users, :manager])
    |> Ecto.Changeset.change
    |> Ecto.Changeset.put_assoc(:users, [users_to_inject])
    |> Repo.update!
    
  3. 这会导致以下错误:

** (ArgumentError) invalid changes being applied to changeset. Expected a keyword list or a map, got: [%BackEndService.Users.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 2, username: "Sec User", email: "[email protected]", hash_password: "$pbkdf2-sha512$160000$jUnAuyThExRqhgSfqCzT.Q$H4ReypEz5DDfqBcTqANbWe0t2Z0hOTM5.YXU2EJCvyV2PViVIPSmPEXPpaNRwhUxaRh59cQ1NwCP4SqBHSA9yQ", grade: 20, clocks: [], teams: [%BackEndService.Teams.Team{__meta__: #Ecto.Schema.Metadata<:loaded, "teams">, id: 1, description: "Rapide descriptiumlorem ipsum", title: "Équipe N1", date_creation: ~N[2023-10-25 15:05:34], manager_id: 1, manager: #Ecto.Association.NotLoaded<association :manager is not loaded>, users: #Ecto.Association.NotLoaded<association :users is not loaded>, inserted_at: ~U[2023-10-27 13:11:48Z], updated_at: ~U[2023-10-27 13:11:48Z]}, %BackEndService.Teams.Team{__meta__: #Ecto.Schema.Metadata<:loaded, "teams">, id: 2, description: "Rapide descriptiumlorem ipsum", title: "Équipe N2", date_creation: ~N[2023-10-25 15:05:34], manager_id: 1, manager: #Ecto.Association.NotLoaded<association :manager is not loaded>, users: #Ecto.Association.NotLoaded<association :users is not loaded>, inserted_at: ~U[2023-10-27 14:09:37Z], updated_at: ~U[2023-10-27 14:09:37Z]}], inserted_at: ~U[2023-10-26 14:38:32Z], updated_at: ~U[2023-10-26 14:38:32Z]}]

我错过了什么吗?

PS :这是我在 plateform 上的第一个问题,所以不要犹豫,提供更好的问题编辑技巧

[编辑]:即使users_to_inject只包含一个条目,问题仍然是一样的

数据库 错误处理 Elixir 对多 ECTO

评论

0赞 Yatender Singh 10/30/2023
github.com/yatender-oktalk/misobo/blob/master/lib/misobo/......你能检查一下我的回购吗?在你的问题中,看起来已经是一个列表,你又在包装它。users_to_inject
0赞 Lucas 10/30/2023
哦,我明白。。。但是在那之后,我收到一个新错误:“您正在尝试更改关系:用户\nBackEndService.Teams.Team,但此关系的选项\n设置为.\n\n默认情况下,无法替换或删除嵌入和\n关联。:on_replace:raisecast

答:

2赞 Lucas 10/30/2023 #1

我修复了多个错误来解决这种情况:

  1. 正如辛格@Yatender在评论中提到的那样,我正在包装一些不需要它的东西。事实上,信息已经以良好的格式从何处检索。Repo.all()
  2. 我的架构缺少关系上的属性。必须根据我的需要进行设置(这里删除所有以前的数据以替换为新数据)。其中给出了以下行users_teams:on_replacemany_to_many :users, BackEndService.Users.User, join_through: "users_teams", on_replace: :delete
  3. 最后,我用而不是|> Repo.update!|> Repo.update()

评论

0赞 Yatender Singh 10/31/2023
我很高兴,我可以帮忙。