Rails 在幂等种子文件中查找或创建 - 不通过验证

Posted

技术标签:

【中文标题】Rails 在幂等种子文件中查找或创建 - 不通过验证【英文标题】:Rails find or create by in idempotent seeds file - not passing validations 【发布时间】:2015-11-12 18:46:42 【问题描述】:

在创建Users 及其与每个Account 的关联时,我正在尝试使用find_or_create_by 创建一个幂等种子文件。

我创建了一个Accounts 列表,并希望将User 关联到每个帐户。

用户模型在email 上有一个uniqueness 验证。

在我第一次运行种子文件时,帐户和用户已创建并关联,并且可以正常工作。

但是在我第二次运行种子文件时,我得到了Validation failed: Email has already been taken

如果我运行,我会收到验证错误。

Account.first.users.find_or_create_by!(email: email)

我的印象是find or create by 返回第一条记录或创建新记录。但它似乎只是创建了一条新记录,即使它存在,也没有找到以前的用户记录。

如果我打电话

User.find_or_create_by!(email: email)

返回该电子邮件的用户。

【问题讨论】:

不确定您要对 Account.users.find_or_create_by!(email: email) 做什么,因为 Account 看起来像一个类而不是其实例。事实上,find_or_create_by! 应该通过这些属性找到用户。 apidock.com/rails/v4.0.2/ActiveRecord/Relation/… 抱歉,我更新了我的问题以获取第一个 Account,但它似乎仍然不起作用。嗯 【参考方案1】:

您尝试创建的用户可能在该帐户中不存在。

Account.first.users.find_or_create_by!(email: email)

如果第一个帐户中没有用户的电子邮件,那么它将尝试创建一个。但是,您无法创建该用户,因为电子邮件已被占用。

User.find_or_create_by!(email: email)

之所以有效,是因为它会检查任何用户,而不仅仅是第一个帐户中的用户。

如果您希望它始终正确运行,您可以执行类似的操作

Account.first.users << User.find_or_create_by!(email: email)

如果你知道 users 数组是空的。或者可能,

User.find_or_create_by!(email: email).update_attributes(:account_id => Account.first.id)

【讨论】:

我想我很困惑,我以为 Account.first.users.find_or_create_by!(email: email) 最初会创建该用户并将其与该帐户相关联? 我将如何无缝地建立这种关联? Account.first.users.find_or_create_by!(email: email, account_id: Account.first.id) @srm 是的,它会创建一个用户并将其与该帐户相关联。但是创建部分不是问题所在,它没有在用户数组中找到用户,所以它继续创建一个。但是正如您所说,该电子邮件已经有一个用户,因此创建失败。如果您改为在 User 模型上 find_or_create,您将找到一个用户而不是创建一个用户。 我从不在帐户上创建用户时调用创建操作。我想我需要深入挖掘并弄清楚为什么用户没有与该帐户关联。 @srm 您的测试数据可能会保留在测试数据库中。我还没有看到你所有的代码,所以我在这里做一些假设,但如果第一次运行代码成功,那么我假设第二次运行不成功,因为第一次数据持续存在,现在你有验证错误。试试我上面的代码 sn-ps 看看它们是否适合你。如果您从未事先创建它们,那么您为什么首先需要find_or_create_by!

以上是关于Rails 在幂等种子文件中查找或创建 - 不通过验证的主要内容,如果未能解决你的问题,请参考以下文章

Rails 3 从单个数据库表生成种子文件

如何从磁力链接或 infohash 创建种子文件

在Rails 4.1中,如何通过枚举符号查找记录?

主动存储种子 Rails

Rails6.0.0 + Faker + Devise +种子

浅谈常用接口中的幂等设计