代码之家  ›  专栏  ›  技术社区  ›  script

为整个关联生成变更集

  •  1
  • script  · 技术社区  · 7 年前

    我读到了 cast_assoc/3 single changeset for the entire association 并在一个事务中执行它以进行更新。这是我的模型

        defmodule User do      
         use Gallery.Web, :model
    
    
         schema "users" do   
           field(:name, :string)
           field(:occupation, :string)
           has_many(:paintings, Painting)
         end
    
        def changeset(struct, params \\ %{}) do
         struct
         |> cast(params, [ :name, :occupation ])
         |> validate_required([:name, :occupation]) 
        end
       end
    
       defmodule Painting do      
         use Gallery.Web, :model
    
    
         schema "paintings" do   
           field(:name, :string)          
           belongs_to(:users, User)
         end
    
        def changeset(struct, params \\ %{}) do
         struct
         |> cast(params, [ :name ])
         |> validate_required([:name]) 
        end
       end
    

    这是我想要构建单个变更集的数据

    data= %User{
        __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
       id: 4606,
       name: "Test",
       occupation: "Artist",
       paintings: [
         %Painting{
         __meta__: #Ecto.Schema.Metadata<:loaded, "paintings">,
         user_id: 4606,
         id: 1515,
         name: "philip"
         },
       %Painting{
        __meta__: #Ecto.Schema.Metadata<:loaded, "paintings">,
        user_id: 4606,
        id: 1516,
        name: "john"
        }
      ]
     }
    

    有什么建议吗?

    谢谢

    1 回复  |  直到 5 年前
        1
  •  1
  •   tkowal    7 年前

    如果只想插入具有多幅绘画的用户,则需要:

    • 清除结构
    • 有一个 cast_assoc 在用户变更集中

    data = %{
      name: "Test",
      occupation: "Artist",
      paintings: [
        %{
          name: "philip"
        },
        %{
          name: "john"
        }
      ]
    }
    
    %User{}
    |> User.changeset(data)
    |> Repo.insert
    

    如果你也想用这种方式更新东西,那就更复杂了。目前尚不清楚这些画的清单是否在 data 数据 . 我个人不建议对更新使用嵌套的变更集。 https://hexdocs.pm/ecto/Ecto.Changeset.html#cast_assoc/3

    澄清后更新:

    要更新所有的画,你还需要做两件事。你需要:

    • 预装画
    • 在数据中有绘画id

    这样地:

    data = %{
      name: "Test",
      occupation: "Artist",
      paintings: [
        %{
          id: 1,
          name: "philip"
        },
        %{
          id: 2,
          name: "john"
        }
      ]
    }
    
    User
    |> Repo.get_by(id: user_id)
    |> Repo.preload(:paintings)
    |> User.changeset(data)
    |> Repo.update
    

    Multi Repo 模块一次通常表示一个数据库操作。

    所有的魔法都发生在 paintings: [...]

    • 如果参数不包含ID,则参数数据将传递给带有新结构的changeset/2,并成为插入操作
    • 新建结构并成为插入操作
    • 如果参数包含一个ID,并且有一个与此ID相关联的子级,则参数数据将传递给changeset/2
    • 如果有一个ID为的关联子级,并且其ID未作为参数给定,则该关联的:on\u replace回调将 已调用(请参阅模块文档中的On replace部分)

    数据