Я делаю GET запрос в Typeform. Если запрос выполнен успешно, я сохраняю ответ как 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
Наверное, я неправильно сформулировал вопрос. Попробую сделать понятнее. В моей базе данных есть 2 заказа, у одного Landing_id XXX, а у другого YYY. Теперь пользователь решает отправить новую форму. Поэтому я делаю запрос GET к Typeform, но этот Typeform Response имеет посадочный_id ZZZ. До сих пор в моей базе нет заказа с посадочным_идентификатором ZZZ. Таким образом, будет создана новая запись. Теперь проблема в том, что он также создает дублирующую запись для Landing_id XXX и YYY. Извините за грамматику, я один телефон.
Я бы посоветовал вам добавить гем byebug и отладить свой код. Я не понимаю, зачем создавать более одного заказа, но я не знаю, что сейчас items. Отладьте запрос шаг за шагом, и я думаю, вы обнаружите, что создает дополнительные заказы.





Документация Active Record для найти_или_создать_по:
Please note this method is not atomic, it runs first a SELECT, and if there are no results an INSERT is attempted. If there are other threads or processes there is a race condition between both calls and it could be the case that you end up with two similar records.
В любом случае вы можете обойти эту проблему, добавив ограничение uniq к комбинации столбцов user_id и landing_id:
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
won't find a landing_id and therefore will create all orders again. But those orders already exist in the databaseВы говорите, что он не найдетlanding_id, и вы говорите, что заказы существуют, но вы ищете поlanding_id, если заказы существуют, вы должны искать по полю, которое существует.