我正在向Typeform发出GET
请求。如果请求成功,则将响应另存为order
到数据库。我的问题在于这一特定部分:
current_user.find_or_create_by(landing_id: item["landing_id]) do |order|
如果用户提交新的Typeform,则该方法将找不到landing_id
,因此将再次创建所有orders
。但是这些orders
已经存在于数据库中,因此每个order
被多次保存到我的数据库中。
如何避免这种情况?
items = response.parsed_response["items"]
items.each do |item|
@order = current_user.orders.find_or_create_by(landing_id: item["landing_id"]) do |order|
order.landing_id = item["landing_id"]
order.email = item["hidden"]["email"]
order.price = item["hidden"]["price"]
order.project = item["hidden"]["project"]
order.save!
end
end
答案 0 :(得分:0)
find_or_create_by的Active Record文档:
请注意此方法不是原子的,它首先运行SELECT,如果没有结果,则尝试INSERT。如果还有其他线程或进程,则这两个调用之间存在竞争状态,并且最终可能会有两个相似的记录。
无论如何,您可以通过为user_id
和landing_id
列的组合添加uniq约束来解决此问题:
add_index :orders, [:user_id, :landing_id], unique: true
并相应地更改代码:
items = response.parsed_response["items"]
items.each do |item|
begin
Order.transaction(requires_new: true) do
@order = current_user.orders.find_or_create_by(landing_id: item["landing_id"]) do |order|
order.landing_id = item["landing_id"]
order.email = item["hidden"]["email"]
order.price = item["hidden"]["price"]
order.project = item["hidden"]["project"]
order.save!
end
end
rescue ActiveRecord::RecordNotUnique
next
end
end