Запись создается несколько раз, несмотря на проверку (проблема со временем)

#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'