有没有办法通过变更集只更改关系中的第一项?阿卡,如果我有:
account
N emails
可以做类似的事情:
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
或者解决此类问题的最佳方法是什么?
答案 0 :(得分:1)
在处理数据库时,不应该依赖任何顺序(除非显示明确的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
。