使用 ECTO 和 put_assoc/4 进行多对多

2024-02-12

我尝试将 2 个现有多对多记录与 ECTO 和 put_assoc/4 关联,但在尝试更新时不会删除元素。

基本上我有项目和用户。为了管理用户对项目的访问,我有表“user_project”。

def Project do
    schema "project" do
    ...
    # users (if user_type is :admin)
    many_to_many(
    :users,
    User,
    join_through: "user_project"
    )
    ...
    end
end

def User do
    schema "user" do
    ...
    # users (if user_type is :admin)
    many_to_many(
    :projects,
    User,
    join_through: "user_project"
    )
    ...
    end
    ...
    def changeset_insert_not_active(%User{} = user, attrs) do
            user
            |> cast(attrs, @required_fields)
            |> put_assoc(:projects, attrs.projects)
            |> validate_required(@required_fields)
            |> validate_user_type()
            |> validate_format(:email, ~r/@/)
            |> unique_constraint(:email)
    end
    ...
    def changeset_update_projects(%User{} = user, projects) do
            user
            |> cast(%{}, @required_fields)
            # associate projects to the user
            |> put_assoc(:projects, projects)
    end
    ...
end

def Management do
    ...
    def create_user(attrs \\ %{}, project_ids \\ []) when is_list(project_ids) do

        projects =
        Project
        |> where([project], project.id in ^project_ids)
        |> Repo.all()

        %User{}
        |> User.changeset_insert(attrs 
        |> Map.put(:projects, projects))
        |> Repo.insert()
    end
    ...
    def upsert_user_projects(user, project_ids) when is_list(project_ids) do
        projects =
        Project
        |> where([project], project.id in ^project_ids)
        |> Repo.all()

        user
        |> User.changeset_update_projects(projects)
        |> Repo.update()
    end
    ...
end

当我使用项目列表创建用户时,所有内容都已创建,但是当尝试更新用户项目时,删除对一个项目的访问权限时,什么也没有发生...

例如:

test "xxx" do 
    Management.upsert_user_projects(user, [1])
    l = Management.list_user_project_by_user(user.id)
    IO.puts("---------")
    IO.puts("1 - length:#{length(l)}")
    IO.puts("---------")
    Enum.each(l, fn project ->
        IO.inspect(project.project_id, label: "inserted project_id ")
    end)

    Management.upsert_user_projects(user, [2])
    l = Management.list_user_project_by_user(user.id)

    IO.puts("---------")
    IO.puts("2 - length:#{length(l)}")
    IO.puts("---------")
    Enum.each(l, fn project ->
        IO.inspect(project.project_id, label: "inserted project_id ")
    end)
end

返回值:

---------
1 - length:1
---------
inserted project_id : 1
2 - length:2
---------
inserted project_id : 1
inserted project_id : 2

为什么?为什么 put_assoc/4 只添加新元素而不删除?


@IvanYurov 是对的。您需要定义 on_replace 选项,但还需要更新用户的预加载(在每个请求中)。基本上,为了使测试正确,您需要在 Management.upsert_user_projects(user, ...) 之前执行 user=get_user (预加载项目)。

def get_user(id) do
  Repo.get(User, id)
  |> Repo.preload(:projects)
end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 ECTO 和 put_assoc/4 进行多对多 的相关文章

随机推荐

  • 在 Android 设置中防止“匹配的 Activity 可能不存在”

    大部分活动操作 用于启动各种设置活动 Settings http developer android com reference android provider Settings html类带有警告 在某些情况下 匹配的活动可能不存在 因
  • 如何使用正则表达式和 Java 计算文本中的音节

    我有文字作为String并需要计算每个单词的音节数 我尝试将所有文 本拆分为单词数组 然后分别处理每个单词 我为此使用了正则表达式 但音节模式并没有发挥应有的作用 请建议如何更改它以计算正确的音节数 我的初始代码 public int ge
  • ZipInputStream.getNextEntry 在某些 zip 文件上返回 null

    我有一个简单的代码来提取 zip 文件 它按预期工作得很好 但在测试过程中 我尝试使用一些 zip 文件 我从互联网下载的字体 图标和模板 来编写代码 以确保它应该提取任何 zip 文件已提供 但它不适用于某些 zip 文件 以下是重新生成
  • nginx 未知指令“上游”

    我使用 nginx 作为代理服务器将请求转发到我的 Gunicorn 服务器上 当我跑步时sudo nginx t c etc nginx sites enabled mysite我收到以下错误 emerg unknown directiv
  • Swift:为蓝牙中央管理器选择队列

    我正在开发一个应用程序 该应用程序将通过 BLE 与智能设备连接并与其通信 问题是 在哪个队列中处理蓝牙事件的最佳实践是 我读过很多教程 在所有教程中我发现了这一点 centralManager CBCentralManager deleg
  • 重命名存储库名称后更新origin

    我正在尝试将我的项目文件推送到我的存储库 但是当我这样做时 我会收到如下屏幕截图所示的错误 我之前在该项目文件中有一个存储库 然后将其删除 现在我在该项目文件中创建了另一个具有不同名称的存储库 但我现在收到这些错误 请告诉我应该做什么 将源
  • 向下滚动时,滚动 100vh 到底部

    我想达到同样的效果http www squaredot eu Intro http www squaredot eu Intro 因此 如果我向下滚动 正文必须滚动 100vh 到底部 而且如果向上滚动 主体必须向上滚动 100vh 我尝试
  • 如何在Python中启用辅助轴(twiny)的共享

    我正在尝试启用主轴和辅助轴的共享 下面的代码说明了示例图 该图包含两个水平轴 主轴网格显示为绿色 而另一个轴网格显示为红色 usr bin python coding utf 8 import numpy as np import matp
  • Android 模拟器:如何复制模拟器/AVD?

    我目前正在对 Google 应用商店 又名 Google Play 上已有的现有应用程序进行升级 我想测试客户升级时数据转换是否顺利 我有一个 AVD 安装了旧版本的应用程序 通常的做法是在此应用程序上运行新版本 看看它是否有效 但问题是
  • 了解 mod_proxy 和 Apache 2 以编写 comet-server

    我目前尝试为某种类型实现一个简单的 HTTP 服务器comet http en wikipedia org wiki Comet programming 技术 长轮询 XHR 请求 作为JavaScript对于跨域请求非常严格我有几个问题
  • Python/Tkinter - 单击时识别对象

    我正在尝试创建一个程序 根据先前的颜色将单击时的对象颜色从白色更改为黑色或从白色更改为黑色 我希望程序仅在对象是矩形时才更改颜色 我怎样才能让这一切发生 这是我的代码 import tkinter as tk root tk Tk cv t
  • 如何从firebase实时数据库获取字符串数组

    databaseReference FirebaseDatabase getInstance getReference sample databaseReference addValueEventListener new ValueEven
  • Python Pandas:当日期小于 13 时,pandas.to_datetime() 会切换日期和月份

    我编写了一个读取多个文件的代码 但是在我的一些文件中 每当日期小于 13 时 日期时间就会交换日期和月份 并且从第 13 天或以上开始的任何一天 即 13 06 11 仍然正确 DD MM YY 我试图通过这样做来修复它 但它不起作用 我的
  • django admin - 您无权编辑任何内容

    我跟着Django 文档 https docs djangoproject com en 1 8 topics auth customizing a full example创建自定义用户模型 同时使用我自己的字段扩展模型本身 于是就变成了
  • 在本地主机上启动 Jupyter Notebook 会导致“[Errno 49] 无法分配请求的地址”,但 ip=127.0.0.1 有效

    尝试启动 Jupyter Notebook 时出现以下错误 Jupyter Notebook Traceback most recent call last File Library Frameworks Python framework
  • ASP.Net Core JWT 令牌验证

    我需要验证在请求中收到的多个令牌 我遵循以下代码流程 services AddAuthentication AddJwtBearer Token1 options gt options TokenValidationParameters n
  • 是否可以调用不在 MATLAB 路径中的函数?

    我安装了一个库 其中有一些与 MATLAB 同名的函数 通过安装库 我的意思是添加路径 当我尝试调用这些函数时 它将使用该库的实现 但我想调用 MATLAB 实现 为了更简单 如果我有两个函数的绝对地址 如何指定要调用哪个函数 我搜索了答案
  • Github 访问错误 - 遇到 AggregateException [重复]

    这个问题在这里已经有答案了 我使用 github 存储库已经快一年了 从今天早上开始 我无法将我的代码推送到远程存储库 我在命令行中收到以下错误 致命 遇到 AggregateException Mindestens ein Fehler
  • 在使用 Inno Setup 安装期间报告已安装的 .NET Framework 版本

    我正在尝试使用 Inno Setup 来准备创建安装程序 我的第一次尝试是向用户报告当前安装了哪个 NET Framework 我想出了以下脚本 它安装了一个令牌 exe 但它没有显示我想要显示已安装的框架版本的消息框 Setup AppN
  • 使用 ECTO 和 put_assoc/4 进行多对多

    我尝试将 2 个现有多对多记录与 ECTO 和 put assoc 4 关联 但在尝试更新时不会删除元素 基本上我有项目和用户 为了管理用户对项目的访问 我有表 user project def Project do schema proj