ensure_no_related_objects.rb 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. class Webhook::EnsureNoRelatedObjects
  3. attr_reader :record
  4. def self.before_destroy(record)
  5. new(record).before_destroy
  6. end
  7. def self.referencing_models
  8. # this cache doesn't need to be cleared as the result won't change
  9. @referencing_models ||= Models
  10. .all
  11. .keys
  12. .select { |klass| klass.column_names.include? 'perform' }
  13. end
  14. def initialize(record)
  15. @record = record
  16. end
  17. def before_destroy
  18. return if record.new_record?
  19. ensure_no_related_objects!
  20. end
  21. private
  22. def ensure_no_related_objects!
  23. return if related_objects.blank?
  24. raise Exceptions::UnprocessableEntity, "Cannot delete! This webhook is referenced by #{references_text}"
  25. end
  26. def related_objects
  27. @related_objects ||= self.class.referencing_models.each_with_object({}) do |model, result|
  28. performables = referencing_performables(model)
  29. next if performables.blank?
  30. result[model.name] = performables
  31. end
  32. end
  33. def referencing_performables(model)
  34. model.find_each.with_object([]) do |performable, result|
  35. next if !webhook_referenced?(performable)
  36. result.push({
  37. id: performable.id,
  38. name: performable.name
  39. })
  40. end
  41. end
  42. def webhook_referenced?(performable)
  43. record.id == performable.perform
  44. &.dig('notification.webhook', 'webhook_id')
  45. &.to_i
  46. end
  47. def references_text
  48. related_objects.map do |model, performables|
  49. performables_text = performables.map { |performable| "#{performable[:name]} (##{performable[:id]})" }.join(', ')
  50. "#{model}: #{performables_text}"
  51. end.join(', ')
  52. end
  53. end