将某些变更集字段强制转换为ecto:map字段

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

我有一个看起来像这样的变更集:

%{
  creator_id: "4",
  name: "a test with GraphQL",
  place_id: "13",
  entree_id: "8",
  base: "wheat",
  type: "food"
}

我的ecto架构如下:

schema "items" do
  field :type, :string
  field :name, :string
  field :data, :map

  belongs_to :creator, Name.SubName.Creators
  belongs_to :place,   Name.SubName.Places
  belongs_to :entree,  Name.SubName.Entrees

  timestamps()
end

正如你所看到的,base不是ecto模式中的一个字段,我想将base强制转换为data字段,以便它是map类型,即:{"base":"wheat"}。我在这里使用某种形式的单表继承。

我想在我的items表中添加一条记录。现在当我从表中读到时,我将data字段转换为包含我的type字段的嵌入式模式(取决于base)。我努力的地方是把这个领域带回数据库。

我尝试使用像Ecto.Changeset.cast(params[:base], Map.keys(%{data: :map}))这样的东西,但显然只是获得了显然不是有效地图的价值。另外,指定与代表每个type的其他嵌入式模式相关联的所有唯一字段将是痛苦的。

embeds_oneembeds_many不适用于这种情况,因为data ecto字段表示不同的嵌入式模式类型。因此,在这种情况下,我的问题不是关于嵌入式模式使用,而是更多关于在changeset中选择特定字段并将它们变成map。我的一半只是认为我应该为每个type制作一个独特的表格,然后我不必担心这一点。

elixir ecto single-table-inheritance
1个回答
1
投票

你可以使用Map.split/2

@required_fields [:name, :type, :creator_id, :place_id, :entree_id]
@all_fields [:data | @required_fields]

def changeset(struct, params) do
  {allowed, others} = Map.split(params, @required_fields)
  params = Map.put(allowed, :data, others)

  struct
  |> cast(params, @all_fields)
  |> # ...
end

这里需要注意的重要一点是,此示例仅适用于具有原子键的映射,您必须稍微修改它以使用字符串和原子键。您还可以考虑将空映射指定为:data的默认值。

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