我有一个父组件和一个子组件。我想在孩子的同时创建父母,因为父母在没有孩子的情况下不能存在。具体来说,我有一个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
这是一个鸡蛋鸡问题:数据库引擎将唯一ID分配给主记录。因此,在单个事务中执行此操作是不可能的。
唯一的可能性是自己处理主表上的ID
键,通过DB内部函数生成GUID(如MySQL中的UUID()
,或PostgreSQL中的CREATE SEQUENCE
)。在这种情况下,可以事先调用此函数并明确设置ID
。
不过,我不建议使用后一种方法。
这是一个古老的问题,但回答以防有人像我一样落在这里。
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
这应该做的工作