#ruby-on-rails #validation
Вопрос:
Веб-крючок с большим количеством обработки создает запись, которая должна пройти эту проверку:
validates_uniqueness_of :pipedrive_deal_id, :allow_blank => true, scope: [:experience_id, :time], unless: -> { pipedrive_deal_id.zero? }
Обработка этого веб-крючка генерирует дополнительные вызовы того же веб-крючка. Это приводит к тому, что одна и та же запись создается 4 раза, не соблюдая проверку, показанную выше.
Я «исправил» проблему, поставив «спящий режим 5» при последующих вызовах webhook, что, по-видимому, дает начальному процессу достаточно времени для «закрытия»? проверка и отклоняет любые последующие попытки ее создания.
Есть ли менее хитрый способ решить эту проблему?
Вот код метода (я удалил некоторые вещи, чтобы сделать его более понятным):
def self.create_or_update_from_pipedrive(params, won_or_update,changed_values=nil)
#this method calls the same webhook
hosting_link = PipedriveService.hosting_platform_setup(params[:id])
if won_or_update == ('won')
Payment.add_deal(params)
else
#this is the offending sleep 5
sleep 5
end
#....internal processing
if booking.update( booking_params)
if booking.tour.present?
if booking.tour.time != booking.time
#this calls the webhook again
booking.add_to_tour
end
end
end
if params[Rails.configuration.pipedrive_hash[:trip_details]].include? '40'
if booking.update(booking_params)
if booking.tour.present?
if booking.tour.time != booking.time
#this calls the webhook again
booking.add_to_tour
end
end
end
#this calls the webhook again
PipedriveService.set_post_session_activities(params, booking_time) if won_or_update == 'won'
end
Спасибо
Комментарии:
1. Да, есть менее хакерский способ, наложите уникальное ограничение на эти поля в вашей базе данных, это сделает невозможным сохранение дубликатов.
2. Как мне поместить уникальное ограничение с областью действия в БД?
3. @wachichornia Вы можете создавать уникальные индексы для любого количества столбцов, сколько вам нужно
4. Нашел его. Недостающим фрагментом было » где » в конце:
Ответ №1:
Вам нужен уникальный индекс в базе данных. Это даже упоминается в официальных руководствах по рельсам.
https://guides.rubyonrails.org/active_record_validations.html#uniqueness
Этот помощник проверяет уникальность значения атрибута непосредственно перед сохранением объекта. Это не создает ограничения уникальности в базе данных, поэтому может случиться так, что два разных подключения к базе данных создадут две записи с одинаковым значением для столбца, который вы хотите сделать уникальным. Чтобы избежать этого, вы должны создать уникальный индекс для этого столбца в своей базе данных.
Ответ №2:
На случай, если кто-нибудь наткнется на мою проблему, решением будет (как указано в других ответах) уникальный индекс в базе данных. Что касается части «если атрибут не равен нулю», вот вся команда миграции, чтобы добавить и это:
add_index :bookings, [:pipedrive_deal_id, :time,:experience_id], unique: true, where: 'pipedrive_deal_id > 0'