elixir - 修改变更集中的第一条相关记录
问题描述
有没有办法通过变更集仅更改关系中的第一项?也就是如果我有:
- 1
account
与Nemails
可以执行以下操作:
schema "accounts" do
...
has_many(:emails, StockrtApi.Accounts.Email)
end
def changeset(account, params) do
account
...
|> cast_assoc(:emails, required: true, with: &Email.changeset(&1, &2))
|> put_change(first_email_only, {primary: true}) # <- might have to go in email schema
end
或者解决此类问题的最佳方法是什么?
解决方案
处理数据库时不应依赖任何事物的顺序(除非提供了显式ORDER BY
子句。)虽然大多数数据库驱动程序将返回一个没有显式ORDER BY
子句的可预测的有序集,但这绝不是保证。也就是说,总是更喜欢显式而不是隐式:只需引入另一个through
关联:
schema "accounts" do
...
has_many :emails, StockrtApi.Accounts.Email
has_one :primary_email, through: [:primary_email, :email]
end
并把这个联想与平常Ecto.Changeset.put_assoc/4
。
根据评论,当您只需要确保有电子邮件时,请执行以下操作:
defp ensure_email(
%Ecto.Changeset{errors: errors, changes: %{emails: emails}} = changes
) do
case emails do
[] ->
new_errors = [{:emails, {"can’t be empty", [validation: :emails]}}]
%{changes | errors: new_errors ++ errors, valid?: false}
_ -> changes
end
end
并明确使用它:
def changeset(account, params) do
account
...
|> cast_assoc(:emails, required: true, with: &Email.changeset(&1, &2))
|> ensure_email()
end
这样您就可以确保至少存在一封电子邮件 - 只需将第一封用作primary
.
推荐阅读
- maven - 有没有人有关于如何将基于 aspectj 的 maven 模块移植到 bazel 的参考资料
- jquery - 如何根据数据列表选择更改表单动作属性值
- google-cloud-platform - 无法使用 GPU 创建 GCP AI Platform Notebook。它说配额“GPUS_ALL_REGIONS”超出。限制:全局 0.0
- python - 如何在不刷新页面的情况下使用提交表单按钮?
- javascript - Node.JS - 为什么等待不等待
- google-apps-script - 选择状态时将 2 列数据移动到不同的选项卡
- python - 如何每次将变量保存到文本文件到新行?
- firebase - 如何在提供者登录时在 Firebase Auth 中定义 UID
- react-native - 需要帮助在 React Native 项目中实现 RNCamera
- python - 为什么 ImageStat 返回有符号整数图像的错误统计信息(`mode='I'`)?