Mil*_*lan 2 ruby-on-rails ruby-on-rails-4
我有这样的事情:
types = ['landline', 'cell']
Phone.find_or_create_by(person_id: 1, type: types) do |record|
record.number = '0'
end
Run Code Online (Sandbox Code Playgroud)
这行不通。不会创建新记录。但是当我重写它看起来像这样:
types = ['landline', 'cell']
types.each do |type|
Phone.find_or_create_by(person_id: 1, type: type) do |record|
record.number = '0'
end
end
Run Code Online (Sandbox Code Playgroud)
有用。
有什么想法为什么find_or_create_by
不能将数组作为条件?
很好的问题,这是我的示例解释。
find_or_create_by
首先运行a select query
,然后继续create method
api文档中有一个find_or_create_by注释,
请注意,此方法不是原子方法,它首先运行SELECT,如果没有结果,则尝试INSERT。如果还有其他线程或进程,则这两个调用之间存在竞争条件,并且最终可能会有两个相似的记录。
因此,当运行此命令时,它将首先运行select查询。
例如,让我获取一个用户表,并从控制台结果中显示该表。
我的用户test222@example.com
数据库中有电子邮件,但没有test333@example.com
。
User.find_or_create_by(email: ['test222@example.com','test333@example.com'])
现在,当我运行时,find_or_create_by
这是生成的查询。
User Load (175.5ms) SELECT
用户.* FROM
用户WHERE
用户.
电子邮件IN ('test222@example.com', 'test333@example.com') LIMIT 1
回应是
=> #<User id: 82, provider: "email", uid: "test222@example.com", name: nil, nickname: nil, image: nil, email: "test222@example.com", created_at: "2016-09-05 12:35:01", updated_at: "2016-09-05 12:35:01">
因此它返回找到的用户,并且没有运行create方法,而忽略了未找到(第二封电子邮件)
现在,如果我循环运行它,
emails = ['test222@example.com','test333@example.com']
emails.each do |email|
User.find_or_create_by(email: email)
end
Run Code Online (Sandbox Code Playgroud)
将针对第二封电子邮件运行INSERT查询,
**INSERT INTO `users` (`email`,`created_at`, `updated_at`) VALUES ('test@ead.com', '2016-10-07 13:16:25', '2016-10-07 13:16:25')**
Run Code Online (Sandbox Code Playgroud)
您的情况也是如此。
归档时间: |
|
查看次数: |
1446 次 |
最近记录: |