在Ecto中同时创建与所需foreign_id的父,子嵌套关联

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

我有一个父组件和一个子组件。我想在孩子的同时创建父母,因为父母在没有孩子的情况下不能存在。具体来说,我有一个subscriptions has_many services

如果我的子模型的必需字段是外部约束,我该如何同时创建两个模型?我的变更集中出现错误,表明parent.id不能为空。

我知道我可以做Repo.insert!(Subscription)然后用Service创建一个subscription.id变换集,但我想知道是否有可能同时创建两个?

我的父母和子女变更集列在下面:

家长(订阅)

def changeset(struct, params \\ %{}) do
# get the current time and add 30 days.
    {:ok, active_until} = DateTime.utc_now()
      |> DateTime.to_unix() |> Kernel.+(2592000) |> DateTime.from_unix()

    struct
    |> change(active_until: active_until)
    |> cast(params, [:active_until, :user_id])
    |> cast_assoc(:services)
    |> validate_required([:active_until])
end

孩子(服务)

def changeset(struct, params \\ %{}) do
    struct
    |> cast(params, [:start_time, :frequency, :subscription_id])
    |> validate_required([:subscription_id])
    |> foreign_key_constraint(:subscription_id)
end
elixir phoenix-framework ecto
2个回答
1
投票

这是一个鸡蛋鸡问题:数据库引擎将唯一ID分配给主记录。因此,在单个事务中执行此操作是不可能的。

唯一的可能性是自己处理主表上的ID键,通过DB内部函数生成GUID(如MySQL中的UUID(),或PostgreSQL中的CREATE SEQUENCE)。在这种情况下,可以事先调用此函数并明确设置ID

不过,我不建议使用后一种方法。


0
投票

这是一个古老的问题,但回答以防有人像我一样落在这里。

def changeset(%Subscription{} = subscription, attrs) do
  subscription
  |> cast(attrs, [...])
  |> ...
  |> cast_assoc(:services, required: true)
  |> ...
end

def create_subscription(attrs \\ %{}) do
  %Subscription{}
  |> Subscription.changeset(attrs)
  |> Repo.insert()
end

这应该做的工作

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